Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jQuery: $.when deferred AJAX calls — one failed call cancels others

I'm making multiple API calls, after which I want to load the combined results of each call:

$.when(
    $.get(localAPI, data, function(response) {
        globalStore.localShares = Number(response);
    }),

    $.get(facebookAPI, '', function(response){
        globalStore.facebookShares = Number(response[0].share_count);
    }),

    $.getJSON(pinterestAPI, {url: url}).done(function(response){
        globalStore.pinterestShares = Number(response.count);
    })
).always(function(){
   //Do stuff
});

If the $.get calls fail, the $.always callback function still executes.

But

If just one $.get call fails, it negates the actions of the previous calls.

So, if the first call fails, globalStore returns with two items. If the first call succeeds but the second fails, globalStore returns with only one item. And if the first two calls succeed but the last one fails, globalStore returns empty.

Is there any way around this?

Edit:

Yes, I have tried to handle fails within $.when like this:

$.when(
    $.get(mu30_ajax_frontend.ajaxurl, data, function(response) {
        globalStore.localShares = Number(response);
    }).fail(function(){
        globalStore.localShares = 0;
    }),

    $.get(facebookAPI, '', function(response){
        globalStore.facebookShares = Number(response[0].share_count);
    }).fail(function(){
        globalStore.facebookShares = 0;
    }),

    $.getJSON(pinterestAPI, {url: url}).done(function(response){
        globalStore.pinterestShares = Number(response.count);
    }).fail(function(){
        globalStore.pinterestShares = 0;
    })
).always(function(){
   //Do stuff
});

But I get the same result.

like image 911
ibhhvc Avatar asked Feb 10 '16 19:02

ibhhvc


1 Answers

There's no way around this when using $.when that way, if one request fails, the entire chain fails.

You'd have to roll your own instead, using deferreds to know when the calls are all completed, and always successfully resolving etc.

var defs = [new $.Deferred(), new $.Deferred(), new $.Deferred()];

$.get(localAPI, data, function(response) {
    globalStore.localShares = Number(response);
    defs[0].resolve(true);
}).fail(defs[0].resolve);

$.get(facebookAPI, '', function(response){
    globalStore.facebookShares = Number(response[0].share_count);
    defs[1].resolve(true);
}).fail(defs[1].resolve);

$.getJSON(pinterestAPI, {url: url}).done(function(response){
    globalStore.pinterestShares = Number(response.count);
    defs[2].resolve(true);
}).fail(defs[2].resolve);

$.when.apply($, defs).then(function(result) {
    // result is an array, any true value is a successful request "[true, true, true]"
});

written verbosely, this could be prettied up with some functions and loops etc.

like image 157
adeneo Avatar answered Sep 30 '22 04:09

adeneo