Q.all 在 NodeJS 中如何工作?

How does Q.all work in NodeJS?

我有以下代码:

var a = [1,2,3,4,5];
var promises = [];
a.forEach(function(item,index){
    var deferred = Q.defer();
    doSomething().then(function(){
        deferred.resolve(true);
        promises.push(deferred);
    });
});

Q.all(promises).then(function(data){
    console.log("something!!");
});

Q.all 如何知道 promises 数组具有 forEach 循环所需的所有 promise? 有时,我的 Q.all 在 forEach 之前运行。请告诉我哪里错了。

doSomething() 是一个异步函数,它 returns 一个承诺。

问题是执行Q.all时,promises数组还是空的。延迟对象被异步推送到 promises,因此 Q.all() 将在 doSomething() 的承诺得到解决之前执行。

Q.all 不能在 forEach 之前 运行,因为 forEach 是同步的。

但实际上在 Q.all 被调用后,你将内容推送到数组中。您使用承诺的方式有点笨拙:无需在承诺中使用延迟!

另外,在拒绝或解决它之后,您不想推动延迟本身,而是推动它持有的承诺。有关如何 "promisify" 异步函数的更多信息,请参见下文。

Deffered 用于从简单的基于回调的异步代码中定义承诺。由于 doSomething() returns 一个承诺(你正在使用 .then()),你实际上可以这样做:

var a = [1,2,3,4,5];
var promises = [];
a.forEach(function(item,index){
    var promise = doSomething().then(function(data){
        return Q(true);
    });
    promises.push(promise);
});

Q.all(promises).then(function(data){
    console.log("something!!");
});

然后 promises 将直接填充 promises,没有任何延迟。

编辑:由于您询问的是 doSomething 未启用承诺,因此您可以执行以下操作:

假设 doSomething 将在某个异步任务后执行的回调作为参数。

然后你可以这样包装 doSomething:

function doSomethingPromise(){
    var defered = Q.defer();
    doSomething(function(err,data){
       if(err){
           defered.reject(err);
       }
       else{
           defered.resolve(data);
       }
    });
    return defered.promise;
}

然后使用上面提到的 doSomethingPromise(),而不是 doSomething,因为这个 returns 是一个承诺。