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