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

我想有一个for循环每次迭代调用asynchronous函数。

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

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

代码部分用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; } 

我创build了一个jsFiddle,可以在这里findhttp://jsfiddle.net/riemersebastian/B43u6/3/ 。

目前看起来执行顺序没问题(请参阅控制台输出)。

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

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

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

你需要使用的是$ q.all ,它将许多promise合并成一个只有在所有的promise都被解决的时候才被parsing的promise。

在你的情况下,你可以做这样的事情:

 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; } 

使用新的ES7,您可以以更直接的方式获得相同的结果:

 let promises = angular.forEach( $scope.testArray, function(value){ writeSome(value); }); let results = await Promise.all(promises); console.log(results); 

您可以使用$q和'reduce'来链接promise。

 function setAutoJoin() { var deferred = $q.defer(), data; var array = _.map(data, function(g){ return g.id; }); function waitTillAllCalls(arr) { return arr.reduce(function(deferred, email) { return somePromisingFnWhichReturnsDeferredPromise(email); }, deferred.resolve('done')); } waitTillAllCalls(array); return deferred.promise; } 

这对我使用ES5语法

 function outerFunction(bookings) { var allDeferred = $q.defer(); var promises = []; lodash.map(bookings, function(booking) { var deferred = $q.defer(); var query = { _id: booking.product[0].id, populate: true } Stamplay.Object("product").get(query) .then(function(res) { booking.product[0] = res.data[0]; deferred.resolve(booking) }) .catch(function(err) { console.error(err); deferred.reject(err); }); promises.push(deferred.promise); }); $q.all(promises) .then(function(results) { allDeferred.resolve(results) }) .catch(function(err) { allDeferred.reject(results) }); return allDeferred.promise; }