3

So I have the following code:

function ajax1(url) {
    return $.ajax({
        url: url
    });
}

function ajax2(url) {
    return $.ajax({
        url: url
    });
}

function ajax3(url) {
    return $.ajax({
        url: url
    });
}

function ajax4(url) {
    return $.ajax({
        url: url
    });
}

I then run the Ajax calls and access the data returned by each one using $.when:

$.when(ajax1(url), ajax2(url), ajax3(url), ajax4(url)).done(function(a1, a2, a3, a4){

});

Now, let's say one of the Ajax calls, ajax2, will return a 404 error.

How can prevent the script from executing and still return something (like false, to be accessed using the a2 variable) even when a 404 error is returned?

Thank you very much in advance.

Sergiu Tripon
  • 183
  • 2
  • 14

3 Answers3

4

jQuery 3 Deferreds are Promises A+ compliant. That means you can add a catch() to the request promise

Whenever you return from a catch() it resolves the promise and whatever is returned will be passed to the next then() in the chain

function ajax1(url) {
  return $.ajax({
      url: url
    })
    .then(data => data)
    .catch(resolveFailure);
}

function resolveFailure(jqXhr) { 
  // return whatever you want here. I added the status in case that is of interest
  // could return `false` or string or whatever
  // can also log any issues back to server if needed
  return {
    error: true,
    status: jqXhr.status,
    statusText: jqXhr.statusText
  };
}

var req = ajax1('https://api.myjson.com/bins/l9ywp'),
    req2 = ajax1('https://httpbin.org/FAIL'),
    req3 = ajax1('https://api.myjson.com/bins/l9ywp');

// could also replace `$.when with `Promise.all()`
$.when(req, req2, req3).then(function(r1, r2, r3) {
  // validate the arguments based on whatever you return in the catch()
  console.log('r1', r1);
  console.log('r2', r2);// object returned from catch()
  console.log('r3', r3);
});
.as-console-wrapper {max-height: 100%!important;top:0}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • Thanks a lot for this! This is what I want. One question, is the `.then(data => data)` required in `ajax1()`? The syntax doesn't seem right. – Sergiu Tripon Jan 11 '18 at 07:29
  • It's arrow function syntax equivalent to `then(function(data){ return data})`. It's up to you what you want to see in `$.when`. If you use `Promise.all()` instead of `$.when` only the data will show up without that step – charlietfl Jan 11 '18 at 10:57
0

Instead of calling done() from $.when(), try then() like so:

https://jsfiddle.net/L83ny70k/

In the JSFiddle check your console to see the response from the failed request!

JQuery's when().then() can take 2 functions, the first will trigger if all requests resolve, similar to how done() works, the second will trigger if any of the requests fails and will pass the response of that failed request through to your function so you can do what you will with it!

Hope that helps :)

More info

https://api.jquery.com/jquery.when/

https://api.jquery.com/deferred.then/

EDIT: This solution will stop you from accessing the responses for all other successful requests. Thanks for pointing that out @charlietfl!

Andrew Salib
  • 115
  • 1
  • 11
0

The last bit on the $.when() documentation has something that might help you:

Execute the function myFunc when both ajax requests are successful, or myFailure if either one has an error.

Example:

$.when( $.ajax( "/page1.php" ), $.ajax( "/page2.php" ) )
  .then( myFunc, myFailure );

Now, if you want to know the failure for individual calls, you can also get individual status codes for each call, so that a call like:

function ajax2(url) {
    return $.ajax({
        url: url
    });
}

could get converted to something like:

function ajax2(url) {
    var isGoodResponse = $.ajax(url).always(function(xhr){
         console.log(xhr);
         // do whatever checks you want here
         return xhr.statusCode === '404';
    });
    // returns true/false
    return isGoodResponse;
}

For example:

$.ajax("http://false-url.duh")
    .always(function(xhr){
        console.log(xhr);
    }
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
blurfus
  • 13,485
  • 8
  • 55
  • 61
  • Don't see how this answers OP question. Op wants it so regardless of status `myFunc` fires always and myFailure never fires – charlietfl Jan 11 '18 at 01:36