I'm trying to use $q.all to wait until all promises are resolved but it's called after first promise is finished!
What I'm doing wrong?
function sendAudits(audits) {
var promises = [];
$scope.sendAudits = {
progress: 0
};
angular.forEach(audits, function (audit, idAudit) {
promises.push(saveAudit(audit));
});
$q
.all(promises)
.then(function (data) {
console.log(data);
}, function (errors) {
console.log(errors);
});
}
function saveAudit(audit) {
var filename = audit.header.id + ".txt";
return $http({
method: 'PUT',
url: '/audits/audits.php?filename=' + encodeURIComponent(filename),
data: AuditSvc.getPlainAudit(audit.header.id)
}).finally(function () {
$scope.sendAudits.progress += 1;
console.log("FINALLY: " + audit.header.id);
});
}
EDIT
Analysing a little bit deeper the problem, this situation occurs when some of the responses are error. For example when the server returns header("HTTP/1.0 418 I'm A Teapot: " . $filename);
, client console would be like:
PUT http://localhost:8182/audits/audits.php?filename=1.txt 418 (I'm A Teapot: 1.txt)
FINALLY: 1
Object {data: "", status: 418, config: Object, statusText: "I'm A Teapot: 1.txt"}
PUT http://localhost:8182/audits/audits.php?filename=2.txt 418 (I'm A Teapot: 2.txt)
FINALLY: 2
PUT http://localhost:8182/audits/audits.php?filename=3.txt 418 (I'm A Teapot: 3.txt)
FINALLY: 3
PUT http://localhost:8182/audits/audits.php?filename=4.txt 418 (I'm A Teapot: 4.txt)
FINALLY: 4
$q.all
is not resilient
As noted by others, $q.all
is not resilient. If one of the promises is rejected, the $q.all
is rejected with the first error.
To create a resilient composite promise, that is a promise that waits for all the promises to complete pass or fail, use .catch
on each individual promise to convert the rejected promise to a successful promise.
var resilientPromises = [];
angular.forEach(promises, function(p) {
var resilientP = p.catch( function(result) {
//return to convert rejection to success
return result;
});
resilientPromises.push(resilientP);
});
$q.all(resilientPromises).then( function (results) {
//process results
});
The two things to take away from this answer:
$q.all
promise is not resilient. It is rejected with the first rejected promise..then
method or the .catch
method.For more information, see You're Missing the Point of Promises
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With