0
votes

I have a function that loads a section.

function loadSection(sectionId, onLoaded) {
    $.when(
        loadTemplate(sectionId),
        // etc
    )
    .then(function () {
        // removed for brevity
    }
}

In the loadTemplate function I fade out the current template, and after the fadeout I load the new template.

function loadTemplate(sectionId) {
    // Fade out current template.
    return $content.fadeOut(function () {
        // After fade out, load new template via ajax.
        $.ajax({
            url: settings.apiUrl + 'GetSectionTemplate',
            data: { sectionId: sectionId },
            type: 'post',
            success: function (template) {
                // Add new content and fade in new template.
                $content
                    .html(template)
                    .fadeIn();
            }
        });
    });
}

The problem is that the $.when only waits for the fadeOut function to finish before moving on. I need it to wait for both the fadeOut and the ajax call to finish, but I need the ajax call to execute only after the fadeOut finishes.

3
What if you return $.ajax({}); ?Ian
@ianpgall The return returns from the fadeOut callback function. I tried that. It doesn't fix anything.Chev
Your loadTemplate function needs to participate in the deferred/promise world.jfriend00

3 Answers

2
votes

Create a deferred object, return it, and then resolve it when the ajax completes:

function loadTemplate(sectionId) {
    var deferred = $.Deferred();
    $content.fadeOut(function () {
        $.ajax({
            url: settings.apiUrl + 'GetSectionTemplate',
            data: { sectionId: sectionId },
            type: 'post',
            success: function (template) {
                $content.html(template).fadeIn();
                deferred.resolve();
            }
        });
    });
    return deferred;
}
1
votes

Just use an Array to push the Promise objects into and return that. Like

function loadTemplate(sectionId) {
    var promises = [ ];

    // Fade out current template.
    promises.push($content.fadeOut());
    promises.push($.ajax({
        url: settings.apiUrl + 'GetSectionTemplate',
        data: { sectionId: sectionId },
        type: 'post',
        success: function (template) {
            // Add new content and fade in new template.
            $content
                .html(template)
                .fadeIn();
        }
    }));

    return promises;
}

and then call it like

$.when.apply( null,
    loadTemplate(sectionId)
).then(function() {
});

If you need more control over the order of promise-objects resolve or you want to intercept / filter results, you can also use .pipe() to somewhat concat the promises.

-1
votes

Try making your ajax call synchronous:

 $.ajax({
    async: false,
    url: settings.apiUrl + 'GetSectionTemplate',
    ...
    ...