简体   繁体   中英

How do I use .when() with a function containing an ajax call?

I've seen .when() and .then() used directly with .ajax calls in jquery to delay the execution of a callback function until the ajax is done. What I'm having trouble with is doing the same for functions that are not ajax calls themselves, but contain an ajax function. I've got the following chunk of code:

$(function() {

    $('.document').on('click', '.ajax', ajaxFunction);

});

function ajaxFunction(e) {
        e.preventDefault();

        // ajax request
        $.ajax({
            async: true,
            cache: false,
            type: 'post',
            url: '/echo/html/',
            data: {
                html: '<p>This is echoed the response in HTML format</p>',
                delay: 1
            },
            dataType: 'html',
            beforeSend: function() {
                console.log('Fired prior to the request');
            },
            success: function(data) {
                console.log('Fired when the request is successfull');
                $('.document').append(data);
            },
            complete: function() {
                console.log('Fired when the request is complete');
            }


        });

        console.log('hello world!');
    }

function defferedFunction(d){
    $.when(ajaxFunction(e)).then(alert('hi mom!'))
}

My goal was to fire the alert ('hi mom!') when the contents of the ajaxFunction function were complete, ie when the ajax was done and 'hello world!' had logged to the console. However, the alert never comes up.

The problem, so far as I can tell, is that the container function doesn't actually return a promise, and hence the .then() section never fires. How can I modify this code to return a promise when all of the internal code, including the ajax, is finished?

I'd prefer to continue using the .when() / .then() pattern rather than manually including a callback in ajaxFunction .

A fiddle of the above example is here.

You can return a promise

function ajaxFunction(e) {
        e.preventDefault();

        // ajax request
     return $.ajax({       // return promise  
            async: true,
            cache: false,
            type: 'post',
            url: '/echo/html/',

A couple of things. Like @pXL stated you need to return the promise. Also in your fiddle you need to pass the (d) parameter from your defferedFunction to your ajaxFunction. Finally change your .then to .done(function(a){});

http://jsfiddle.net/mq4Sj/5/

$(function() {

    $('.document').on('click', '.ajax', defferedFunction);

});

 function defferedFunction(e){
        $.when(ajaxFunction(e)).done(function(d){
        alert(d); // ->> response from server.
 })
    }

I figured out that I can do this by creating a deferred event for the whole function, a deferred event for the non-ajax behavior that I want to capture, resolving the second deferred event after the non-ajax stuff is done, and then using a $.when() to capture when both the deferred object returned by the ajax call is resolved and when the deferred object I created for the non-ajax stuff is done, and then using a .then() to resolve the deferred object for the whole function.

It looks like this, all put together:

$(function() {

    $('.document').on('click', '.ajax', defferedFunction);

});

function ajaxFunction(e) {
        e.preventDefault();

        // ajax request
        var ajaxDeferred = $.ajax({
            async: true,
            cache: false,
            type: 'post',
            url: '/echo/html/',
            data: {
                html: '<p>This is echoed the response in HTML format</p>',
                delay: 1
            },
            dataType: 'html',
            beforeSend: function() {
                console.log('Fired prior to the request')

            },
            success: function(data) {
                console.log('Fired when the request is successfull');
                $('.document').append(data);
            },
            complete: function() {
                console.log('Fired when the request is complete');
            }
        })

        var newDeferred = $.Deferred()

        var timeoutDeferred = $.Deferred()

        setTimeout(function(){
            console.log('hello world!')
            timeoutDeferred.resolve()
        }, 2000)

        $.when(timeoutDeferred, ajaxDeferred).then(function(){
            newDeferred.resolve()
        }
        );


        return newDeferred;
    }

function defferedFunction(e){
    $.when(ajaxFunction(e)).done(function(){alert('all done!')})
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM