dabadaba
dabadaba

Reputation: 9522

$.when() with array of Deferreds not calling done action

I am trying to use a variable set of deferred functions in an array along with $.when(). These functions fetch data from the server and render it in the DOM. After all these are done, some scripts are loaded and a couple post-load actions are performed.

Here is what I am using:

function loadAllGames(updateGames, updatePlayoffs) {
    var deferredLoads = [];
    if (updateGames !== false)
        deferredLoads.push($.Deferred(loadGames));

    if (updatePlayoffs !== false)
        deferredLoads.push($.Deferred(loadPlayoffs));

    $.when.apply($, deferredLoads).done(loadPostGamesLoadData);
}

The problem is that loadPostGamesLoadData is never being called.

Both loadGames and loadPlayoffs return promises:

function loadGames() {
    $.get('{% url wave_spinner_template %}', {message: 'Loading games...'}, function (data) {
        $('#weeks').html(data);
    });

    return $.ajax({
        url: "{% url weeks season.id %}",
        success: function (data) {
            $('#weeks').html(data);
        },
        error: function () {
            console.log("Error loading games.");
        }
    });
}

function loadPlayoffs() {
    $.get('{% url wave_spinner_template %}', {message: 'Loading playoffs...'}, function (data) {
        $('#playoffs').html(data).children('.spinner-container').addClass('border-top');
    });

    return $.ajax({
        url: "{% url playoffs season.id %}",
        success: function (data) {
            var $playoffs = $('#playoffs');
            if (!$playoffs.length) {
                $playoffs = $('<div>', {id: 'playoffs'});
                $('#weeks').after($playoffs);
            }
            $playoffs.html(data);
        },
        error: function () {
            console.log("Error loading playoffs.");
        }
    });
}

Upvotes: 0

Views: 54

Answers (2)

T.J. Crowder
T.J. Crowder

Reputation: 1074555

You're creating the deferred objects incorrectly; indeed, you shouldn't be creating them at all. The function accepted by $.Deferred is a factory function run just before $.Deferred returns which receives the new deferred object as an argument (so you can attach handlers to it). (Details in the API docs.) That's not what loadGames and such do at all; they return a deferred object. So you end up with deferred objects that nothing ever settles.

Since they already have deferred objects from $.ajax, which you're returning, just use those functions directly:

function loadAllGames(updateGames, updatePlayoffs) {
    var deferredLoads = [];
    if (updateGames !== false)
        deferredLoads.push(loadGames());
// ------------------------^^^^^^^^^^^

    if (updatePlayoffs !== false)
        deferredLoads.push(loadPlayoffs());
// ------------------------^^^^^^^^^^^^^^

    $.when.apply($, deferredLoads).done(loadPostGamesLoadData);
}

Upvotes: 0

adeneo
adeneo

Reputation: 318252

Drop the Deferred calls, as $.ajax already returns a deferred.

function loadAllGames(updateGames, updatePlayoffs) {
    var deferredLoads = [];
    if (updateGames !== false)
        deferredLoads.push(loadGames());

    if (updatePlayoffs !== false)
        deferredLoads.push(loadPlayoffs());

    $.when.apply($, deferredLoads).done(loadPostGamesLoadData);
}

Upvotes: 1

Related Questions