usar promesas promesa como catch array all angularjs promise angular-promise deferred

angularjs - como - angular $ q, cómo encadenar múltiples promesas dentro y después de un for-loop



promesa angular js (4)

Con el nuevo ES7 puedes obtener el mismo resultado de una manera mucho más directa:

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

Quiero tener un for-loop que llame a las funciones asincrónicas en cada iteración.

Después de for-loop quiero ejecutar otro bloque de código, pero no antes de que se hayan resuelto todas las llamadas anteriores en for-loop.

Mi problema en este momento es que, o bien el bloque de código después de for-loop se ejecuta antes de que todas las llamadas asincrónicas hayan finalizado O no se ejecute en absoluto.

La parte del código con FOR-loop y el bloque de código después de ella (para ver el código completo, vea el fiddle ):

[..] 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; }

Creé un jsFiddle que se puede encontrar aquí fiddle .

Por el momento, parece que el orden de ejecución es bueno (consulte la salida de la consola).

Mi suposición es que esto es simplemente porque cada llamada de función regresa inmediatamente sin hacer ningún trabajo real. He intentado retrasar la resolución defer.resolve con setTimeout pero falló (es decir, el último bloque de código nunca se ejecutó). Puedes verlo en el bloque outcommented en el violín.

Cuando uso las funciones reales que escriben en un archivo y leen desde el archivo, el último bloque de código se ejecuta antes de que finalice la última operación de escritura, que no es lo que quiero.

Por supuesto, el error podría estar en una de esas funciones de lectura / escritura, pero me gustaría verificar que no haya nada de malo en el código que he publicado aquí.


Esto funcionó para mí usando la sintaxis de 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; }


Lo que necesita usar es $q.all que combina una cantidad de promesas en una que solo se resuelve cuando se resuelven todas las promesas.

En tu caso, podrías hacer algo como:

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


Puede usar $q y ''reducir'' juntos, para encadenar las promesas.

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