我需要一些帮助来处理JavaScript中的异步调用。我有一个for循环,每个循环调用一个异步HttpRequest,并将其响应添加到一个数组。我希望程序等到所有异步调用完成后再继续jQuery(仅用于DOM操作)。我已经搜索了很多解决方案但没有真正有用,没有大量更改我的代码或依赖jQuery。
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) => "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 })更新:使用Promise编辑,但仍然无法正常工作,也许我做错了。
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) => "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); })推荐答案
使用promise,您不应使用 callback 参数。改为从承诺中调用 resolve / 拒绝函数。
With promises, you should not use a callback parameter. Call the resolve/reject functions from the promise instead.
不是将回调传递给调用,而是在 .then 处理程序中使用promise的结果链接你要做的事情。
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.
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) => "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); }); })更多推荐
JavaScript等待所有异步调用完成
发布评论