What happens to $ q.all () when some calls work while others fail?

What happens to $ q.all () when some calls work while others fail?

I have the following code:

var entityIdColumn = $scope.entityType.toLowerCase() + 'Id'; var requests = $scope.grid.data .filter(function (rowData, i) { return !angular.equals(rowData, $scope.grid.backup[i]); }) .map(function (rowData, i) { var entityId = rowData[entityIdColumn]; return $http.put('/api/' + $scope.entityType + '/' + entityId, rowData); }); $q.all(requests).then(function (allResponses) { //if all the requests succeeded, this will be called, and $q.all will get an //array of all their responses. console.log(allResponses[0].data); }, function (error) { //This will be called if $q.all finds any of the requests erroring. var abc = error; var def = 99; }); 

When all $ http calls work, the allResponses array is populated with data.

When someone fails, I understand that the second function will be called, and the error variable is the data.

However, can someone explain to me what will happen if some of the answers work and others fail?

+50
javascript angularjs angular-promise
Nov 13 '13 at 3:51
source share
7 answers

I believe that since the promise library is based on the implementation of Q , once the first promise is rejected, the reject callback is called with an error. He does not wait until other promises are resolved. See the Q Documentation https://github.com/kriskowal/q . For Q.all, this is what is mentioned

The whole function returns a promise for an array of values. When this promise is fulfilled, the array contains the execution values โ€‹โ€‹of the original promises, in the same order as promises. If one of the given promises is rejected, the returned promise is immediately rejected, without waiting for the rest of the party.

+35
Nov 13 '13 at 4:16
source share

Some time has passed since this question was posted, but maybe my answer can still help someone. I solved a similar problem at my end by simply resolving all the promises, but with the return I was able to process later and see if there are any errors. Here, my example was used to preload some image objects:

 var loadImg = function(imageSrc) { var deferred = $q.defer(); var img = new Image(); img.onload = function() { deferred.resolve({ success: true, imgUrl: imageSrc }); }; img.onerror = img.onabort = function() { deferred.resolve({ success: false, imgUrl: imageSrc }); }; img.src = imageSrc; return deferred.promise; } 

Later I see which ones are wrong:

 var promiseList = []; for (var i = 0; i < myImageList.length; i++) { promiseList[i] = loadImg(myImageList[i]); } $q.all(promiseList).then( function(results) { for (var i = 0; i < results.length; i++) { if (!results[i].success) { // these are errors } } } ); 
+30
Jun 02 '14 at 10:00
source share

Edit: Supported only by Kris Kowal Q - but still a healthy tidbit

If you want to process all of them without refusing immediately after the failure, use allSettled

Here's what the docs say:

If you want to wait until all promises are fulfilled or rejected, you can use allSettled.

 Q.allSettled(promises) .then(function (results) { results.forEach(function (result) { if (result.state === "fulfilled") { var value = result.value; } else { var reason = result.reason; } }); }); 
+5
01 Oct '14 at 12:40
source share

Here is a short answer. In this script you can see how it works if in some cases an error occurs.

 $q.all([test1(), test2()]).then(function() { // success }, function() { // error }); 

http://jsfiddle.net/wd9w0ja4/

+3
Aug 18 '15 at 7:37
source share

I found a new angular package that adds allSettled functionality to $ q in angular:

https://github.com/ohjames/angular-promise-extras

+2
Aug 14 '15 at 10:55
source share

In my case, I needed to know when the last promise was made regardless of success or failure. $ q.all was not an option, because if it does not work, it will immediately drop. I need this to make sure that the user will be redirected regardless, but only if all the data has been processed (or not) so that it can be downloaded on the next page. So I ended up with this:

  • Keeping every promise / call also cancels the callback when the redirection function is called with both a successful and a fail-safe callback.
  • In this function, a counter is set, which increases with each call. If this number reaches the number of promises / calls, a redirect to the next view is performed.

I know this is a pretty lame way to do this, but it worked for me.

0
Nov 30 '16 at 2:52
source share

Could you just handle the error condition on your $ http promises before passing them to $ q? promises are encoded, so this should work:

 return $http.put('/api/' + $scope.entityType + '/' + entityId, rowData).then(function(r){return r;}, angular.noop); 

Obviously, you can change noop to whatever conversion you want, but this prevents a failure, which prevents the loss of $q.all .

0
Jun 20 '17 at 0:13
source share



All Articles