在JavaScript中,我如何/应该使用XMLHttpRequest的async/await?

jku*_*zak 22 javascript xmlhttprequest async-await

完全披露:我有资格拥有中级JavaScript知识.所以这略高于我此时的经验水平.

我有一个Google Chrome扩展程序,只要file:///页面加载就会为本地执行AJAX请求.在我从请求中得到响应之后,我将在代码中使用多个函数中返回的代码.大部分时间我都会在需要运行的代码之前收到响应.但有时我不会,一切都会破裂.

现在,我假设我可以抛出下面的所有相关代码xhr.onload.但这似乎效率低下?我有许多依赖于响应的活动部件,将它们全部放在那里似乎很糟糕.

我已经阅读了几篇与async/await相关的文章,并且我在理解这个概念时遇到了麻烦.我也不是100%肯定我正在以正确的方式看待这个问题.我是否应该考虑使用async/await?

这是我的AJAX请求的代码.

  var xhr = new XMLHttpRequest();
  xhr.open("GET", url, true);
  xhr.onload = function(e) {
    code = xhr.response;
  };
  xhr.onerror = function () {
    console.error("** An error occurred during the XMLHttpRequest");
  };
  xhr.send();
Run Code Online (Sandbox Code Playgroud)

假设我后来在我的代码中有一些需要触发的函数.现在他们看起来像:

function doTheThing(code) {
  // I hope the response is ready.
}
Run Code Online (Sandbox Code Playgroud)

什么是最好的方法来解决这个问题?仅供参考,FetchAPI不是一种选择.

这是我的代码结构的高级视图.

// AJAX request begins.

// ...

// A whole bunch of synchronous code that isn't dependant on 
// the results of my AJAX request. (eg. Creating and appending
// some new DOM nodes, calculating some variables) I don't want
// to wait for the AJAX response when I could be building this stuff instead.

// ...

// Some synchronous code that is dependant on both my AJAX 
// request and the previous synchronous code being complete.

// ...

// Some more synchronous code that needs the above line to 
// be complete.
Run Code Online (Sandbox Code Playgroud)

Thắ*_*uân 20

我通常做async/await这样:

async function doAjaxThings() {
    // await code here
    let result = await makeRequest("GET", url);
    // code below here will only execute when await makeRequest() finished loading
    console.log(result);
}
document.addEventListener("DOMContentLoaded", function () {
    doAjaxThings();
    // create and manipulate your DOM here. doAjaxThings() will run asynchronously and not block your DOM rendering
    document.createElement("...");
    document.getElementById("...").addEventListener(...);
});
Run Code Online (Sandbox Code Playgroud)

在这里宣传xhr功能:

function makeRequest(method, url) {
    return new Promise(function (resolve, reject) {
        let xhr = new XMLHttpRequest();
        xhr.open(method, url);
        xhr.onload = function () {
            if (this.status >= 200 && this.status < 300) {
                resolve(xhr.response);
            } else {
                reject({
                    status: this.status,
                    statusText: xhr.statusText
                });
            }
        };
        xhr.onerror = function () {
            reject({
                status: this.status,
                statusText: xhr.statusText
            });
        };
        xhr.send();
    });
}
Run Code Online (Sandbox Code Playgroud)

  • @ThắngTrầnXuân 如果我每天都能为你的答案点赞,我会的!!!您刚刚结束了我多年来经历的最令人沮丧的开发会议!谢谢!谢谢!谢谢! (2认同)

Ron*_*ton 12

我为XHR创造了希望。然后只需awaitasync函数内部使用即可调用它。

function getHTML(url) {
    return new Promise(function (resolve, reject) {
        var xhr = new XMLHttpRequest();
        xhr.open('get', url, true);
        xhr.responseType = 'document';
        xhr.onload = function () {
            var status = xhr.status;
            if (status == 200) {
                resolve(xhr.response.documentElement.innerHTML);
            } else {
                reject(status);
            }
        };
        xhr.send();
    });
}

async function schemaPageHandler(){
    try {
        var parser = new window.DOMParser();
        var remoteCode = await getHTML('https://schema.org/docs/full.html');
        var sourceDoc = parser.parseFromString(remoteCode, 'text/html');
        var thingList = sourceDoc.getElementById("C.Thing");
        document.getElementById("structured-data-types").appendChild(thingList);
    } catch(error) {
        console.log("Error fetching remote HTML: ", error);
    }              
}
Run Code Online (Sandbox Code Playgroud)


Jib*_*ose 5

您有两种选择,

首先是使用fetch基于诺言的较新api,与您一起可以

let response = await fetch(url);
response = await response.json();; // or text etc..
// do what you wanna do with response
Run Code Online (Sandbox Code Playgroud)

如果您确实要使用XMLHttpRequest,则另一个选择是使它变大

let response = await new Promise(resolve => {
   var xhr = new XMLHttpRequest();
   xhr.open("GET", url, true);
   xhr.onload = function(e) {
     resolve(xhr.response);
   };
   xhr.onerror = function () {
     resolve(undefined);
     console.error("** An error occurred during the XMLHttpRequest");
   };
   xhr.send();
}) 
// do what you wanna do with response
Run Code Online (Sandbox Code Playgroud)

可能的完整解决方案

(async () => {
   let response = await new Promise(resolve => {
      var xhr = new XMLHttpRequest();
      xhr.open("GET", url, true);
      xhr.onload = function(e) {
        resolve(xhr.response);
      };
      xhr.onerror = function () {
        resolve(undefined);
        console.error("** An error occurred during the XMLHttpRequest");
      };
      xhr.send();
   }) 
   doTheThing(response)
})()
Run Code Online (Sandbox Code Playgroud)