JAVASCRIPT 警告:主线程上的同步 XMLHttpRequest 已被弃用,因为它会对最终用户的体验产生不利影响



我正在尝试构建一个简单的字典chrome扩展。我找到了这个API在线文本,从中(通过HTTP请求(提取了一个由单词细节组成的字符串,并将该字符串解析为JSON对象。但是,当我使用该扩展时,我会收到关于Synchronous XMLHttpRequest的警告。我提供了以下代码:

manifest.json


{
"name": "Dictionary Extension",
"version": "1.0",
"description": "Finds the meaning of the word entered by user",
"browser_action": {
"default_title": "Hello there! What is it that you're looking for",
"default_popup": "popup.html",
"default_icon": {
"16": "dic.png",
"32": "dic.png"
}
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["popup.js"]
}
],
"manifest_version": 2
}

<!--popup.js-->
var url = "https://api.dictionaryapi.dev/api/v2/entries/en_US"
var input = document.getElementById("input");
var button = document.getElementById("btn");
var mat = document.getElementById("material");
function httpGet(theUrl) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", theUrl, false); // false for synchronous request
xmlHttp.send(null);
return xmlHttp.responseText;
}

button.addEventListener("click", function() {
mat.innerHTML = "";
var val = input.value;
var temp_url = url + "/" + val;
var json_data = httpGet(temp_url);
var data = JSON.parse(json_data);
var l = data[0].meanings.length;
for (var i = 0; i < l; i++) {
var len = ((data[0].meanings[i]).definitions).length;
part_of_speech = (data[0].meanings[i]).partOfSpeech;
var h1 = document.createElement("h2");
var list = document.createElement("ol");
h1.innerHTML = part_of_speech;
mat.appendChild(h1);
for (var j = 0; j < len; j++) {
var def = (data[0].meanings[i]).definitions[j].definition;
var li = document.createElement("li");
li.innerHTML = def;
list.appendChild(li);
}
mat.appendChild(list);
}
});
<!--popup.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Find Meaning</title>
</head>
<body>
<h1>Hello there! What is it that you're looking for?</h1>
<label for="word">Enter the word</label>
<input id="input" type="text" placeholder="Word">
<button id="btn">Find Meaning</button>
<div id="material"></div>
<script src="popup.js"></script>
</body>
</html>

这是我试过的。我尝试将函数XMLHttpRequestObject.open((的"async"参数更改为true,但随后,它给出了以下错误:Uncaught SyntaxError:JSON输入意外结束。我对此进行了搜索,得出的结论是,函数httpGet((将在很久之后返回字符串,在此期间,按钮的单击事件上的函数将被执行。所以,现在";数据";变量是";未定义的";因为httpGet的值尚未返回。因此,它无法将undefined解析为json对象。我是Js的新手,对HTTP了解不多。如有任何帮助,我们将不胜感激。

研究async/await和promise,但需要进行的基本更改是:

button.addEventListener("click", async function() {
// ...
var json_data = await httpGet(temp_url);
// ...
})
function httpGet(theUrl) {
return new Promise((resolve, reject) => {
var xmlHttp = new XMLHttpRequest();
xmlHttp.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(xmlHttp.response);
} else {
reject({
status: this.status,
statusText: xmlHttp.statusText
});
}
};
xmlHttp.open("GET", theUrl, true); // true for asynchronous request
xmlHttp.send(null);
});
}

如果我可以对代码进行一点重构/现代化,我会这样做(使用fetch-api而不是旧的XMLHttpRequest(

const url = "https://api.dictionaryapi.dev/api/v2/entries/en_US/"
const [form, material] = document.querySelectorAll("form, #material");
// Using form.onsubmit is better then btn.onclick
// Will allow the form to be validated before this function is triggerd
form.addEventListener("submit", async function (evt) {
evt.preventDefault()
// using promise based fetch API that can be awaited
const res = await fetch(url + form.elements.word.value)
// Choose to return json instead of parsing a string
const data = await res.json()
material.innerHTML = ''
// for..of loop makes it easier
for (const meaning of data[0].meanings) { 
const h1 = document.createElement('h2')
const list = document.createElement('ol')
// using innerText is safer
h1.innerText = meaning.partOfSpeech
material.append(h1)
for (const def of meaning.definitions) {
const li = document.createElement('li')
li.innerText = def.definition
list.append(li)
}
material.append(list)
}
})
<h1>Hello there! What is it that you're looking for?</h1>
<form target="https://api.dictionaryapi.dev/api/v2/entries/en_US/">
<!-- updated the id to match the input element -->
<label for="wordInput">Enter the word</label>
<!-- added the required attribute to the input -->
<input autofocus id="wordInput" name="word" type="text" required placeholder="Word">
<button type="submit">Find Meaning</button>
</form>
<div id="material"></div>

最新更新