Handling multiple promises within an array individually
angularjs, javascript
Solution
Q (on which ng.$q is based on) or bluebird have a method fulfilling exactly your needs.
For bluebird, you'd go this way:
var Promise = require('bluebird');
Promise.settle(arrPromises).then(function(promises) {
promises.forEach(function(p) {
if (promise.isRejected()) {
// it's a rejected promise.
}
else {
// it's a resolved promise.
}
});
});
And for Q, you'd go this way:
var Q = require('q');
Q.allSettled(arrPromises).then(function(promises) {
promises.forEach(function(p) {
if (p.state === 'fulfilled') {
// it's a resolved promise.
}
else {
// it's a rejected promise.
}
});
});
The nice thing about both these libraries is that they're compliant with the Promises/A+ specification. Which means you can take off ng.$q, put one of these, and your current code will still work.
Problem
I have a function which makes web service calls to my server and returns an array of promises. However some of these calls might work while others might not. The way my function is currently set up, if one of them fails, it alerts that the entire thing failed. If I'm making 5 calls, 1 might fail. I need to log this correctly and I'm not sure how to do it. An ideal response/log would be: - call 1 passed - call 2 passed - call 3 passed - call 4 failed - reason - call 5 passed Right now the whole thing will return "The handle user operation failed" because call 4 failed. Function: ``` var manageGroup = function (add, group, users){ var deffered = $q.defer(); var arrPromises = []; var promiseIndex = arrPromises.length; var usersLength = users.length; var operation = add ? "AddUserToGroup" : "RemoveUserFromGroup"; var actionText = add ? "Added: " : "Removed: " var actionText2 = add ? " to " : " from " //Apply operation on selected groups for (var i = 0; i < usersLength; i++){ arrPromises[i] = $().SPServices({ operation: operation, groupName: group.name, userLoginName: users[i].domain }); } $q.all(arrPromises).then( function (){ //when promises are finsihed for (var i = 0; i < usersLength; i++){ console.log(actionText + users[i].name + actionText2 + group.name); }; deffered.resolve(); }, //function incase of AJAX failure function (){ alert('The handle user operation failed.'); } ) return deffered.promise; } ``` I tried to handle the promises individually instead of using the $q.all but now I'm not getting anything in the log: I took this section out: ``` /*$q.all(arrPromises).then( function (){ //when promises are finsihed for (var i = 0; i < usersLength; i++){ console.log(actionText + users[i].name + actionText2 + group.name); }; deferred.resolve(); }, //function incase of AJAX failure function (){ alert('The handle user operation failed.'); } ) */ ``` Introduced this instead: ``` for (var i = 0; i<promiseIndex; i++){ arrPromises[i].then( function (){ console.log(actionText + user[i].name + actionText2 + group.name); } ), function (){ alert('Failed to add/remove'+ user[i].name + ' to ' + group.name) } } $q.all(arrPromises).then(function (){ deferred.resolve(); }, function (){ deferred.reject(); }) ```