【问题标题】:JAVASCRIPT WARNING: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experienceJAVASCRIPT 警告:主线程上的同步 XMLHttpRequest 已被弃用,因为它对最终用户的体验产生不利影响
【发布时间】:2021-08-16 02:36:09
【问题描述】:

我正在尝试构建一个简单的字典 chrome 扩展。我在网上找到了这个 API Text,我从那里(通过 HTTP 请求)获取了一个包含单词详细信息的字符串,并将该字符串解析为 JSON 对象。但是当我使用扩展时,我收到了关于同步 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() 的“异步”参数更改为 true,但随后出现以下错误:Uncaught SyntaxError: Unexpected end of JSON input。我对此进行了搜索,得出的结论是,函数 httpGet() 返回字符串的时间要晚得多,在此期间,执行按钮单击事件的函数。因此,现在“数据”变量是“未定义”,因为尚未返回来自 httpGet 的值。因此,它无法将 undefined 解析为 json 对象。 我是 Js 新手,对 HTTP 不太了解。对此的任何帮助将不胜感激。

【问题讨论】:

    标签: javascript google-chrome-extension get xmlhttprequest manifest.json


    【解决方案1】:

    查看 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);
      });
    }
    

    【讨论】:

    • 感谢您的意见。现在它工作正常。但是对于不存在的单词,它会给出错误;未捕获(承诺)#。我对其进行了搜索,发现它与捕获错误(错误处理)有关。你能在这里指导我吗?谢谢。
    【解决方案2】:

    如果我可以稍微重构/现代化这段代码,我会这样做(使用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>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-16
      • 2015-12-20
      相关资源
      最近更新 更多