Handling multiple promises inside an array individually

I have a function that calls web service calls on my server and returns an array of promises.

However, some of these calls may work, while others may not. The way my function is currently configured, if one of them fails, it warns that the whole thing has failed. If I make 5 calls, 1 may fail. I need to spell it correctly, and I'm not sure how to do it.

The ideal answer / log would be:

  • call 1 passed
  • call 2 passed
  • call 3 passed
  • call 4 failed - reason
  • challenge 5 passed

Currently, all of this will return “Descriptor 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;      
}

promises , $q.all, :

:

/*$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.');
    }
) */

:

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();
})
+3
3

Q ( ng. $q) bluebird , .

bluebird :

var Promise = require('bluebird');

Promise.settle(arrPromises).then(function(promises) {
    promises.forEach(function(p) {
        if (promise.isRejected()) {
            // it a rejected promise.
        }
        else {
            // it a resolved promise.
        }
    });
});

Q :

var Q = require('q');

Q.allSettled(arrPromises).then(function(promises) {
    promises.forEach(function(p) {
        if (p.state === 'fulfilled') {
            // it a resolved promise.
        }
        else {
            // it a rejected promise.
        }
    });
});

, Promises/A+. , ng. $Q, , .

+5

, ajax, all(). AJAX . .

().

, , .

  //store promises to use for all()
  var promises = [];

  //loop for ajax calls
  for (var i=0; i<3; ++i) {
    //new deferred for each call
    var deferred = $q.defer();
    //cache the promise
    promises[i] = deferred.promise;
    //use another function to avoid unwanted variable increment
    makeCall(deferred, i);
  }

  $q.all(promises).then(function(allData) {
    console.log(allData);
  });

  function makeCall(deferred, i) {
    //make the ajax call
    $http.get('file'+i+'.txt').then(function(resp) {
      console.log('Call '+i+' returned.');
        //resolve the promise with ajax data if successful
        deferred.resolve(resp.data);
    }, function() {
      //resolve with something else on failure
      deferred.resolve('');
    });
  }
+4

promises , $q.all,

, , i . :

for (var i = 0; i<promiseIndex; i++) (function(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)
    });
})(i);

then, .

Now every promise is processed individually; but their order is not preserved. For this you will need to use some all, look at @ Florian's answer.


Also note that there is no reason to explicitly use this deffered. Easy return $q.all(arrPromises)! Manually resolving deferred obligations and returning their promises is cumbersome and error prone - in your source code you simply forgot to reject it in case of an error. Do not use this when you already have promises, and can use combinators on them.

+1
source

All Articles