angular $ q,如何在for循环内部和之后链接多个promise

Seb*_*mer 75 promise deferred angularjs angular-promise

我希望有一个for循环,每次迭代都会调用异步函数.

在for循环之后,我想执行另一个代码块,但是在for循环中所有先前的调用都已解决之前.

我现在的问题是,在所有异步调用完成之前执行for循环之后的代码块或者根本不执行它.

带有FOR循环的代码部分和后面的代码块(完整代码,请参见小提琴):

[..]
function outerFunction($q, $scope) {
    var defer = $q.defer();    
    readSome($q,$scope).then(function() {
        var promise = writeSome($q, $scope.testArray[0])
        for (var i=1; i < $scope.testArray.length; i++) {
             promise = promise.then(
                 angular.bind(null, writeSome, $q, $scope.testArray[i])
             );                                  
        } 
        // this must not be called before all calls in for-loop have finished
        promise = promise.then(function() {
            return writeSome($q, "finish").then(function() {
                console.log("resolve");
                // resolving here after everything has been done, yey!
                defer.resolve();
            });   
        });        
    });   

    return defer.promise;
}
Run Code Online (Sandbox Code Playgroud)

我创建了一个jsFiddle,可以在这里找到http://jsfiddle.net/riemersebastian/B43u6/3/.

目前看起来执行顺序很好(参见控制台输出).

我的猜测是,这只是因为每个函数调用都会立即返回而不做任何实际工作.我试图用setTimeout延迟defer.resolve但是失败了(即从未执行过最后一个代码块).你可以在小提琴中的outcommented块中看到它.

当我使用写入文件和从文件读取的实际函数时,最后一个代码块在最后一次写操作完成之前执行,这不是我想要的.

当然,错误可能在其中一个读/写函数中,但我想验证我在这里发布的代码没有任何问题.

Gru*_*nny 120

您需要使用的是$ q.all,它将许多承诺合并为一个承诺,只有在所有承诺得到解决后才能解决.

在你的情况下你可以做类似的事情:

function outerFunction() {

    var defer = $q.defer();
    var promises = [];

    function lastTask(){
        writeSome('finish').then( function(){
            defer.resolve();
        });
    }

    angular.forEach( $scope.testArray, function(value){
        promises.push(writeSome(value));
    });

    $q.all(promises).then(lastTask);

    return defer.promise;
}
Run Code Online (Sandbox Code Playgroud)