I need some help with handling async calls in JavaScript. I have a for loop, each loop calls an async HttpRequest, and adds its response to an array. I want the program to wait until all the async calls are finished before proceeding without jQuery (which is only used for DOM manipulation). I've searched quite bit for solutions but none really worked without heavily changing my code or relying on jQuery.
function httpGet(theUrl, callback) {
var xmlRequest = new XMLHttpRequest();
xmlRequest.onreadystatechange = function() {
if (xmlRequest.readyState == 4 && xmlRequest.status == 200) {
callback(xmlRequest.responseText);
}
}
xmlRequest.open("GET", theUrl, true);
xmlRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlRequest.setRequestHeader("Accept", "application/json");
xmlRequest.send(null);
}
$(document).ready(function() {
var channels = ["freecodecamp", "storbeck", "terakilobyte", "habathcx","RobotCaleb","thomasballinger","noobs2ninjas","beohoff"];
var urls = channels.map((x) => "https://api.twitch.tv/kraken/channels/" + x);
var data = [];
(function(urls, data) {
urls.forEach(function(url) {
function(resolve, reject) {
httpGet(url, function(response) {
data.push(JSON.parse(response));
})
};
})
})(urls, data);
// Continue after all async calls are finished
})
UPDATED: Edited with Promise, but still not working, maybe I did something wrong.
function httpGet(theUrl, callback) {
return new Promise(function(resolve, reject) {
var xmlRequest = new XMLHttpRequest();
xmlRequest.onreadystatechange = function() {
if (xmlRequest.readyState == 4 && xmlRequest.status == 200) {
callback(xmlRequest.responseText);
}
}
xmlRequest.open("GET", theUrl, true);
xmlRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlRequest.setRequestHeader("Accept", "application/json");
xmlRequest.send(null);
})
}
$(document).ready(function() {
var channels = ["freecodecamp", "storbeck", "terakilobyte", "habathcx","RobotCaleb","thomasballinger","noobs2ninjas","beohoff"];
var urls = channels.map((x) => "https://api.twitch.tv/kraken/channels/" + x);
var data = [];
var promises = [];
(function(urls, data) {
urls.forEach(function(url) {
var promise = httpGet(url, function(response) {
data.push(JSON.parse(response));
});
promises.push(promise);
})
Promise.all(promises).then(function() {
console.log(data);
})
})(urls, data);
})
With promises, you should not use a
callback
parameter. Call theresolve
/reject
functions from the promise instead.Instead of passing a callback to the call, chain the things you want to do with the result of the promise in a
.then
handler.Can't it be done by just keeping the count of ajax requests as a variable:
Since you are using jQuery you can use the Deferred Object to chain promises.
Collect all the promises and use
$.when
with spread operator to wait for all promises to resolve. You can usethen
to run a function after all ajax requests are resolved.ES5 Example
ES6 Example