1

I have 3 functions which handle data pulled in from AJAX, they update the page after the ajax function is called.

When the AJAX function is called I show a loader, I want to hide the loader after the AJAX has completed and the functions have completed.

How can I use deferred with when and then in jQuery to test once all 3 function are completed.

Here is my AJAX code, this hides the loader on AJAX success at the moment, ideally this would be after the 3 functions have been completed / were successful.

The 3 functions receive data to process and display on the page, they are not AJAX functions.

function setUpStocking() {
    $.ajax({
        url: url,
        cache: false,
        beforeSend: function(){
            // Show loader
            $('.loader').show();
        },
        success: function(data){

            updateMyList(data.gifts);
            updateRecievedGift(data.recieved);
            updateGiftsOpenedToday(data.opened);

            // Hide loader
            $('.loader').hide();

        }
    });
}

The functions are outside the AJAX function:

function updateMyList(gifts) {
    // Get data, process it and add it to page
}

function updateRecievedGift(recieved) {
    // Get data, process it and add it to page
}

function updateGiftsOpenedToday(opened) {
    // Get data, process it and add it to page
}
zizther
  • 814
  • 1
  • 10
  • 26

2 Answers2

2

You need to first make each of these functions return the deferred object jQuery gives you when you make an AJAX request. Then you can put those in to an array, and apply that to $.when(). Something like this:

var deferreds = [];
$.ajax({
    url: url,
    cache: false,
    beforeSend: function(){
        // Show loader
        $('.loader').show();
    },
    success: function(data){
        deferreds.push(updateMyList(data.gifts));
        deferreds.push(updateRecievedGift(data.recieved));
        deferreds.push(updateGiftsOpenedToday(data.opened));

        $.when.apply(deferreds).done(function() {
            // Hide loader
            $('.loader').hide();
        });    
    }
});
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • Thanks. Do I need to put a promise in the 3 functions? – zizther Dec 08 '14 at 11:11
  • I assume you're already got one if they are making AJAX requests, just use `return $.ajax({ /* settings */ });` – Rory McCrossan Dec 08 '14 at 11:13
  • I have updated my question to show exactly what I have at the moment. I have no deferred or promises at the moment. The AJAX request response get sent to 3 different functions to process the data and add it to the page. Once those 3 functions have been completed I then want to hide the loader. What I have at the moment is the bare essentials with the AJAX request – zizther Dec 08 '14 at 11:24
  • If those functions don't contain any AJAX requests, then they execute synchronously anyway and you don't need to worry about any deferred behaviour. – Rory McCrossan Dec 08 '14 at 11:46
  • Didn't know that, thanks. Would the hide loader method and anything after the functions be called after all 3 functions have completed because they execute synchronously. Thanks – zizther Dec 08 '14 at 12:09
0

There should be $, inside .apply to make above code work.

$.when.apply($, deferreds).done(function() {
    // Hide loader$('.loader').hide();
});