如何等待嵌套的异步jQuery AJAX请求完成?

时间:2021-09-26 19:44:49

I'm using jQuery and I have a loop of asynchronous AJAX requests. I know I can wait for them all to be finished by using the handy '$.when.apply(array_of_requests).then()' method.

我正在使用jQuery,我有一个异步AJAX请求循环。我知道我可以使用方便的'$ .when.apply(array_of_requests).then()'方法等待它们全部完成。

But I also have another set of AJAX requests that are only executed after each of the first requests are finished. I want to wait for them to finish too, but I'm not 100% sure I've found the best way.

但我还有另一组AJAX请求,只有在每个第一个请求完成后才会执行。我想等他们也完成,但我不是100%肯定我找到了最好的方法。

Here's a simplified example of my requests:

这是我的请求的简化示例:

var intital_data = [1,2,3,4,5,6,7,8,9,10];
var promises = [];
var promises_inner = [];

$.each(intitial_data, function(i, n) {
    var ajax_call = $.ajax({url:'http://www.domain.com/etc/'+n});
    promises.push(ajax_call);

    ajax_call.done(function(data) {
        var ajax_call_inner = $.ajax({url:'http://www.domain.com/etc/'+data.result});
        promises_inner.push(ajax_call_inner);

        ajax_call_inner.done(function(data) {
            // Do something with the content of data here.
        });
    });
});

So, when each of the ten looped AJAX requests is done, I make a second AJAX request based on the results of the first. That all works fine.

因此,当完成十个循环AJAX请求中的每一个时,我根据第一个的结果发出第二个AJAX请求。一切正常。

I then have something like this, because I want to wait until both the first ten requests (stored in the promises array) and the second lot (stored in promises_inner) are completed:

然后我有这样的事情,因为我想要等到前十个请求(存储在promises数组中)和第二个批次(存储在promises_inner中)完成:

$.when.apply($, promises).then(
    function() {
        // The ten outer AJAX calls are finished now.

        $.when.apply($, promises_inner).then(
            function() {
                // The inner AJAX calls are finished now.
            }
        );
    }
);

Within the first $.when.apply().then()'s 'done' function the second lot of requests hasn't yet been completed, or even added to the promises_inner array. But I found that adding a nested $.when.apply().then() seems to work - within its 'done' function all the requests have finished.

在第一个$ .when.apply()。then()的'done'函数中,第二批请求尚未完成,甚至已添加到promises_inner数组中。但我发现添加嵌套的$ .when.apply()。then()似乎有效 - 在其“完成”函数中所有请求都已完成。

But I'm not sure this is the best, and most robust, solution. I'm worried that it only works coincidentally - that it's causing just enough delay for the calls to have finished - rather than making logical sense.

但我不确定这是最好,最强大的解决方案。我担心这只会巧合 - 它会导致呼叫完成的延迟 - 而不是合乎逻辑。

Is there a better, more rock-solid, solution? Thanks.

有更好,更坚固的解决方案吗?谢谢。

2 个解决方案

#1


2  

Take a look at $.Callbacks in 1.7. I think you'll be excited about the flexibility of making your own "flows" and the ability to reuse them, run once, etc.

看一下1.7中的$ .Callbacks。我认为你会对制作自己的“流程”的灵活性以及重用它们,运行一次等的能力感到兴奋。

There's nothing wrong with what you did (the apply pattern may not be a first choice of most, they usually just list them in a $.when(a, b, c....)--but you may like the syntax of $.Callbacks better.

你做了什么没有什么问题(应用模式可能不是大多数人的首选,他们通常只是将它们列在$ .when(a,b,c ....)中 - 但是你可能喜欢它的语法$ .Callbacks更好。

#2


0  

Try this with only one main promise to fullfill (resolve) per loop-run (here still called inner_promise).

试试这个只有一个主要的承诺,每个循环运行fullfill(解决)(这里仍称为inner_promise)。

var initial_data = [1,2,3,4,5,6,7,8,9,10];
var promises_inner = [];

initial_data.forEach(function(n) {
    // Create promise for the inner call here.
    var promise_inner = $.Deferred();
    promises_inner.push(promise_inner);

    $.ajax({url:'http://www.domain.com/etc/'+n}).done(function(data) {
        $.ajax({url:'http://www.domain.com/etc/'+data.result}).done(function(data) {
            // Do something with the content of data here.
            promise_inner.resolve();
        });
    });
});
console.log("promises_inner contains " + promises_inner.length + " promises") // should contain all the 10 promises

$.when.apply($,promises_inner).done(function() {
    // The inner AJAX calls are finished now
})

#1


2  

Take a look at $.Callbacks in 1.7. I think you'll be excited about the flexibility of making your own "flows" and the ability to reuse them, run once, etc.

看一下1.7中的$ .Callbacks。我认为你会对制作自己的“流程”的灵活性以及重用它们,运行一次等的能力感到兴奋。

There's nothing wrong with what you did (the apply pattern may not be a first choice of most, they usually just list them in a $.when(a, b, c....)--but you may like the syntax of $.Callbacks better.

你做了什么没有什么问题(应用模式可能不是大多数人的首选,他们通常只是将它们列在$ .when(a,b,c ....)中 - 但是你可能喜欢它的语法$ .Callbacks更好。

#2


0  

Try this with only one main promise to fullfill (resolve) per loop-run (here still called inner_promise).

试试这个只有一个主要的承诺,每个循环运行fullfill(解决)(这里仍称为inner_promise)。

var initial_data = [1,2,3,4,5,6,7,8,9,10];
var promises_inner = [];

initial_data.forEach(function(n) {
    // Create promise for the inner call here.
    var promise_inner = $.Deferred();
    promises_inner.push(promise_inner);

    $.ajax({url:'http://www.domain.com/etc/'+n}).done(function(data) {
        $.ajax({url:'http://www.domain.com/etc/'+data.result}).done(function(data) {
            // Do something with the content of data here.
            promise_inner.resolve();
        });
    });
});
console.log("promises_inner contains " + promises_inner.length + " promises") // should contain all the 10 promises

$.when.apply($,promises_inner).done(function() {
    // The inner AJAX calls are finished now
})