[英]JavaScript Wait until all async calls finish
I need some help with handling async calls in JavaScript.我需要一些帮助来处理 JavaScript 中的异步调用。 I have a for loop, each loop calls an async HttpRequest, and adds its response to an array.我有一个 for 循环,每个循环调用一个异步 HttpRequest,并将其响应添加到一个数组中。 I want the program to wait until all the async calls are finished before proceeding without jQuery (which is only used for DOM manipulation).我希望程序在没有 jQuery(仅用于 DOM 操作)的情况下继续之前等待所有异步调用完成。 I've searched quite bit for solutions but none really worked without heavily changing my code or relying on jQuery.我已经搜索了相当多的解决方案,但没有一个真正有效的没有大量改变我的代码或依赖 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.更新:使用 Promise 进行编辑,但仍然无法正常工作,也许我做错了什么。
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.对于 Promise,您不应该使用callback
参数。 Call the resolve
/ reject
functions from the promise instead.改为从reject
调用resolve
/ reject
函数。
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.不要将回调传递给调用,而是将您想要做的事情与.then
处理程序中的承诺结果链接起来。
function httpGet(theUrl) {
return new Promise(function(resolve, reject) {
var xmlRequest = new XMLHttpRequest();
xmlRequest.onreadystatechange = function() {
if (xmlRequest.readyState == 4) {
if (xmlRequest.status == 200)
resolve(xmlRequest.responseText);
// ^^^^^^^
else
reject(new Error(xmlRequest.statusText)); // or something
}
}
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 promises = urls.map(function(url) {
// ^^^ simpler than forEach+push
var promise = httpGet(url); // <-- no callback
return promise.then(JSON.parse);
});
Promise.all(promises).then(function(data) {
// ^^^^
console.log(data);
});
})
Since you are using jQuery you can use the Deferred Object to chain promises.由于您使用的是 jQuery,您可以使用延迟对象来链接承诺。
Collect all the promises and use $.when
with spread operator to wait for all promises to resolve.收集所有承诺并使用$.when
和 spread 运算符来等待所有承诺解决。 You can use then
to run a function after all ajax requests are resolved.您可以使用then
在解决所有 ajax 请求后运行一个函数。
ES5 Example ES5 示例
$(document).ready(function () { var channels = ["freecodecamp", "storbeck", "terakilobyte", "habathcx", "RobotCaleb", "thomasballinger", "noobs2ninjas", "beohoff"]; var urls = channels.map(function (x) { return "https://api.twitch.tv/kraken/channels/" + x; }); var data = []; var promises = urls.map(function (url) { return $.get(url).then(function (response) { data.push(response); }); }); $.when.apply($, promises).then(function () { console.log('done', data); }); });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
ES6 Example ES6 示例
$(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 = urls.map((url) => $.get(url).then((response) => { data.push(response); })); $.when(...promises).then(function() { console.log('done', data); }); });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Can't it be done by just keeping the count of ajax requests as a variable:难道不能通过将 ajax 请求的计数作为一个变量来完成:
var urls_count, data_count = 0;
function httpGet(theUrl, callback, onComplete) {
var xmlRequest = new XMLHttpRequest();
xmlRequest.onreadystatechange = function() {
if (xmlRequest.readyState == 4 && xmlRequest.status == 200) {
callback(xmlRequest.responseText);
}
if(xmlRequest.readyState == 4){
data_count += 1
if(urls_count == data_count){
//this is called when all ajax calls complete
onComplete();
}
}
}
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 = [];
urls_count = urls.length;
var onComplete = function(){
//your code after all ajax completes.
}
(function(urls, data) {
urls.forEach(function(url) {
function(resolve, reject) {
httpGet(url, function(response) {
data.push(JSON.parse(response));
}, onComplete)
};
})
})(urls, data);
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.