JavaScript 等待所有异步调用完成

标签 javascript asynchronous promise

我需要一些关于处理 JavaScript 中的异步调用的帮助。我有一个 for 循环,每个循环调用一个异步 HttpRequest,并将其响应添加到一个数组中。我希望程序等到所有异步调用完成后再继续,而不使用 jQuery(仅用于 DOM 操作)。我已经搜索了很多解决方案,但没有一个在不大量更改代码或依赖 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
})

更新:用 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);
})

最佳答案

对于 Promise,您不应使用回调参数。而是从 Promise 中调用 resolve/reject 函数。

不要将回调传递给调用,而是将您想要使用 promise 结果执行的操作链接到 .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);
    });
})

关于JavaScript 等待所有异步调用完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34205266/

相关文章:

JavaScript 和 'this' 位于立即执行的函数中

javascript - 如何使用 mat-select 与 react 形式 formarray Angular

C# 异步 TCP 套接字 : Handling buffer size and huge transfers

javascript - 在 JavaScript 模块模式中使用 return {} 的目的是什么?

javascript - Firefox 中的 javascript 错误

javascript - $.ajax beforeSend 不等待其他ajax请求

javascript - 如何处理 Promise 模式中异步调用之前发生的错误?

javascript - 如何减少 Node JS 中多个异步函数的运行时间?

javascript - Nodejs 中的 Promise 使用 Q 将引用保存到 mongoose

Angular : multiple promise wait all