In JavaScript how do I/should I use async/await with XMLHttpRequest?

后端 未结 4 877
不思量自难忘°
不思量自难忘° 2020-11-30 04:23

Full disclosure: I\'d qualify myself as having intermediate JavaScript knowledge. So this is slightly above my experience level at this time.

I\'ve got a Google Chro

相关标签:
4条回答
  • 2020-11-30 05:07

    You get two options,

    first is to use newer fetch api which is promise based, with with you can do

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

    Other option if you really want to use XMLHttpRequest is to promisify it

    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
    

    possible full solution

    (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)
    })()
    
    0 讨论(0)
  • 2020-11-30 05:08

    I usually do async/await like this:

    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(...);
    });
    

    Promisified xhr function here:

    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();
        });
    }
    
    0 讨论(0)
  • 2020-11-30 05:08

    You can for example create an asynchronous class to use instead of the original one. It lacks some methods but it can serve as an example.

    (function() {
        "use strict";
        
        var xhr = Symbol();
        
        class XMLHttpRequestAsync {
            constructor() {
                this[xhr] = new XMLHttpRequest();
            }
            open(method, url, username, password) {
                this[xhr].open(method, url, true, username, password);
            }
            send(data) {
                var sxhr = this[xhr];
                return new Promise(function(resolve, reject) {
                    var errorCallback;
                    var loadCallback;
                    
                    function cleanup()  {
                        sxhr.removeEventListener("load", loadCallback);
                        sxhr.removeEventListener("error", errorCallback);
                    }
                    
                    errorCallback = function(err) {
                        cleanup();
                        reject(err);
                    };
                    
                    loadCallback = function() {
                        resolve(xhr.response);
                    };
                    
                    
                    sxhr.addEventListener("load", loadCallback);
                    sxhr.addEventListener("error", errorCallback);
                    
                    
                    sxhr.addEventListener("load", function load() {
                        sxhr.removeEventListener("load", load);
                        resolve(sxhr.response);
                    });
                    sxhr.send(data);
                });
            }
            set responseType(value)
            {
                this[xhr].responseType = value;
            }
            setRequestHeader(header, value) {
                this[xhr].setRequestHeader(header, value);
            }
        }
        
        addEventListener("load", async function main() {
            removeEventListener("load", main);
    
    
            var xhra = new XMLHttpRequestAsync();
            xhra.responseType = "json";
            xhra.open("GET", "appserver/main.php/" + window.location.hash.substring(1));
            console.log(await xhra.send(null));
            
        });
        
    }());

    0 讨论(0)
  • 2020-11-30 05:16

    I create a promise for the XHR. Then simply use await inside an async function to call it.

    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);
        }              
    }
    
    0 讨论(0)
提交回复
热议问题