2

I found out that my multiple requests work appropriately when they all succeed, but if one of them fails for whatever reason, my callback is not executed. I dug in the jQuery documentation, that says

In the case where multiple Deferred objects are passed to jQuery.when(), the method returns the Promise from a new "master" Deferred object that tracks the aggregate state of all the Deferreds it has been passed. The method will resolve its master Deferred as soon as all the Deferreds resolve, or reject the master Deferred as soon as one of the Deferreds is rejected

Which means that if I submit n requests and they all succeed, the master object will trigger a success resolution, and the connected callback (with .then or .done) will fire. However, if any of those n requests fail, the master Promise will be rejected and I will get a failCallback called when the other subpromises are potentially still working. Additionally, I won't have access to those subpromises in the callback unless I play with closures.

What is the correct way of submitting multiple ajax requests in jQuery and have the same behavior regardless if any of them fail?

Stefano Borini
  • 138,652
  • 96
  • 297
  • 431
  • 1
    Note, might be duplicate of http://stackoverflow.com/questions/5824615/jquery-when-callback-for-when-all-deferreds-are-no-longer-unresolved-either?rq=1, but it was 5 years ago, so maybe there's something for that today. – Stefano Borini Sep 13 '16 at 14:25
  • if you don't mind if you got success or failure, why not use the always() object ? – Stavm Sep 13 '16 at 14:30
  • @polisha989 because always triggers regardless of the resolution status of the master deferred, but that does _not_ mean that when the master object is marked resolved (due to a failure) all other subdeferreds are done. – Stefano Borini Sep 13 '16 at 14:39

2 Answers2

0

It sounds like you want to return success regardless if an individual request fails (assuming too that you would handle this separately) So, a quick suggestion, and forgive me if you've already considered this, is to wrap your AJAX calls in try {} catch {} blocks, to prevent terminal failure within the when() like:

    var ajax1 = function () { //do ajax stuff but return "success" on err
    var ajax2 = function () { //do ajax stuff but return "success" on err 
    
    $.when(ajax1, ajax2).then(doMoreStuff);

and in the ajax functions add something like:

    var ajax1 = function () {
        try {
            $.ajax(function () { 
                success: function(res){ //do stuff}
            });
        } catch () {
            //do nothing, I believe this will return an ok
        }
    }

Or, a different approach:

$.ajax(function () { 
    success: function(){}, 
    error: function () {
        //handle the error 
        return success; 
});

This is almost pseudo code to demonstrate the concept, assuming you can fill in the blanks.

Hope it helps!

Update

In response to your comment. I was thinking something like:

var promise1 = new Promise( function(resolve, reject) {
    $.ajax ({
        success: function () { 
            //do stuff
            resolve("success");
       },
        error: function () { 
            //address your issue
            resolve("success");
    });
});

$.when(promise1, promise2, ...);

I've added a try catch to the original example.

Community
  • 1
  • 1
Wayne F. Kaskie
  • 3,257
  • 5
  • 33
  • 43
  • so basically neutralise the problem, but my deferreds are the ajax promises. I can't try catch the request code, but I can certainly wrap them – Stefano Borini Sep 13 '16 at 14:38
0

I didn't suggest this at first, because it seems that you are working with promises/deferreds that you could list separately, but using $.apply() may work instead. This will run all items in an array "individually".

var promiseArray = [ajax1, ajax2, ...];
$.when.apply($, promiseArray).then(function() { //do the final stuff }

That should run all of them and run .then() even if you have a problem with one.

Wayne F. Kaskie
  • 3,257
  • 5
  • 33
  • 43
  • Nope. If you do apply on an array, it creates a master deferred that `.resolve` when all are resolved, but `.rejects` when any one is rejected. Given that the ajax objects are Deferred-like, when one fails, the master object is rejected, and your then function will not run. – Stefano Borini Sep 13 '16 at 17:26