使用 Promise.all 等待所有回调完成

Using Promise.all to wait until all callbacks have completed

我正在尝试发出两个 HTTP 请求来检索数据,每个请求都有一个回调函数。只有 两个回调函数都完成后,我才想 运行 最后一点代码。也许是我对承诺不熟悉,但我似乎无法让它发挥作用。我只是立即或永远不会得到它 运行 最终的可用代码。

var p1 = getStatus(account1, currency, processStatus)
var p2 = getStatus(account2, currency, processStatus)

Promise.all([p1, p2]).then(function() {
    // evaluate complete status
})

getStatus 是一个 coffeescript 函数,它发出 HTTP 请求,一旦检索到数据,它就会调用提供的回调函数,即第三个参数。

getStatus: (acctId, curr, callback) =>
    options = {url: url, account: acctId, currency: curr}
    new Promise => request options, (err, resp, body) =>
        if !err
            return Promise.resolve callback(null, acctId, curr, JSON.parse(body))

processStatus 是一个 JavaScript 函数,它 运行 遍历检索到的数据。

module.exports.processStatus = function(err, acctId, curr, status) {
    status.forEach(function(s) {
        // ....
    })
    return Promise.resolve(true)
})

如何更改此设置以使 evaluate complete status 代码仅在 两个 processStatus 回调完成后 执行?

您似乎混淆了传递到 new Promise 构造函数的执行程序回调中的静态 Promise.resolve method with the resolve function。正确的是

getStatus: (acctId, curr, callback) =>
    options = {url: url, account: acctId, currency: curr}
    new Promise (resolve, reject) => request options, (err, resp, body) =>
#               ^^^^^^^^^^^^^^^^^
        if !err
            resolve callback(null, acctId, curr, JSON.parse(body))
        else
            reject err

但实际上更好的是

getStatus: (acctId, curr, callback) =>
    options = {url: url, account: acctId, currency: curr}
    new Promise (resolve, reject) =>
        request options, (err, resp, body) =>
            if !err
                resolve body
            else
                reject err
    .then JSON.parse
    .then (status) => callback null, acctId, curr, status

尝试使用反射。参考伪代码。

    // Extend the ability of promise.all() to wait until all promises are resolved/rejected before returning.
    // By default, promise.all() will return if any 1 of the promise pass or fails.
    var reflect = function reflect(promise){
        return promise.then(function(/*resolve return value=*/v){ return { v:v, status: "resolved" }},
            function(/*rejection error=*/e){ return { e:e, status: "rejected" }});
    };


    var promises = [
        new Promise(function(resolve, reject) {
            resolve();
        }),
        new Promise(function(resolve, reject) {
            resolve();
        })
    ];

    Promise.all(promises.map(reflect)).done(function() { resolve(); });