jQuery deferred object with nested ajax calls

2019-02-02 15:22发布

I have a situation in which my ajax calls must perform in a particular order. I have used jQuery Deferred objects in other situations, but cannot seem to find a way to make this behave appropriately.

I have a function which performs a number of ajax requests in it's lifetime. Some of the requests will be performed during the success callback of other requests.

My question: is there a way to return all nested deferred objects to the original $.when call?

A simplified example would be:

function nestedAjax() {
    $.get("/", function(){
        console.log("First ajax done.");
        $.get("/", function(){
            console.log("Second ajax done.");
        });
    });
};

I am trying to have the nestedAjax function to use $.when() and $.done() like so:

$.when(nestedAjax()).done(function(){
    console.log("Complete");
});​

With the console output reading:

> First ajax done.
> Second ajax done.
> Complete.

I can return the first get to achieve this:

> First ajax done.
> Complete.
> Second ajax done.

But obviously this is not what I require. Any help would be appreciated.

3条回答
Explosion°爆炸
2楼-- · 2019-02-02 15:35

Couldn´t add a comment for some reason to the above answer.

So i add my comment here. The above answer will only work if the ajax calls are fast and returns BEFORE the return dfd.promise().

I have the same problem. And as you can see. The returned deferred object states that it is "pending": http://jsfiddle.net/BtEKa/

查看更多
做个烂人
3楼-- · 2019-02-02 15:36

It's actually quite simple. Though all the AJAX calls are Deferred objects, I still use one for the method itself.

function nestedAjax() {
    var dfd = $.Deferred();
    $.get("/echo/json/", function(){
        console.log("First ajax done.");
        $.get("/echo/json/", function(){
             console.log("Second ajax done.");
            dfd.resolve();
        });
    });

    return dfd.promise();
};
查看更多
该账号已被封号
4楼-- · 2019-02-02 15:58

You don't actually need an extra deferred object. You can do what you want by chaining with then():

function nestedAjax() {
    return $.get("/echo/json/").then(function(result1){
        console.log("First ajax done.");
        if (result1) {
            return result1;
        } else {
            return $.get("/echo/json/").then(function(nestedResult){
                console.log("Second ajax done.");
                return nestedResult;
            });
        }
    });
};

I added some logic since I think that's probably the reason you are executing this synchronously. After that you can use the result in $.when like so:

$.when(nestedAjax(), $.get("/something/else")).then(function(nested, other) {
    console.log("Complete.", nested, other);
});
查看更多
登录 后发表回答