用于多个ajax调用的jQuery回调

时间:2022-12-08 20:07:07

I want to make three ajax calls in a click event. Each ajax call does a distinct operation and returns back data that is needed for a final callback. The calls themselves are not dependent on one another, they can all go at the same time, however I would like to have a final callback when all three are complete.

我想在一个click事件中调用三个ajax调用。每个ajax调用执行一个不同的操作,并返回最终回调所需的数据。这些调用本身并不相互依赖,它们都可以同时进行,但是我希望在这三个都完成时得到最终的回调。

$('#button').click(function() {
    fun1();
    fun2();
    fun3();
//now do something else when the requests have done their 'success' callbacks.
});

var fun1= (function() {
    $.ajax({/*code*/});
});
var fun2 = (function() {
    $.ajax({/*code*/});
});
var fun3 = (function() {
    $.ajax({/*code*/});
});

12 个解决方案

#1


93  

Here is a callback object I wrote where you can either set a single callback to fire once all complete or let each have their own callback and fire them all once all complete:

这里是我写的一个回调对象,您可以设置一个回调,在全部完成后触发,或者让每个回调都有自己的回调,并在全部完成后触发:

NOTICE

请注意

Since jQuery 1.5+ you can use the deferred method as described in another answer:

由于jQuery 1.5+可以使用另一个答案中描述的deferred方法:

  $.when($.ajax(), [...]).then(function(results){},[...]);

Example of deferred here

递延的例子在这里

for jQuery < 1.5 the following will work or if you need to have your ajax calls fired at unknown times as shown here with two buttons: fired after both buttons are clicked

对于jQuery < 1.5,以下方法将有效,或者如果您需要在未知的时间触发ajax调用,如下所示,其中有两个按钮:单击两个按钮后触发

[usage]

(使用)

for single callback once complete: Working Example

对于一次完成的回调:工作示例

// initialize here
var requestCallback = new MyRequestsCompleted({
    numRequest: 3,
    singleCallback: function(){
        alert( "I'm the callback");
    }
});

//usage in request
$.ajax({
    url: '/echo/html/',
    success: function(data) {
        requestCallback.requestComplete(true);
    }
});
$.ajax({
    url: '/echo/html/',
    success: function(data) {
        requestCallback.requestComplete(true);
    }
});
$.ajax({
    url: '/echo/html/',
    success: function(data) {
        requestCallback.requestComplete(true);
    }
});

each having their own callback when all complete: Working Example

当全部完成时,每个都有自己的回调:工作示例

//initialize 
var requestCallback = new MyRequestsCompleted({
    numRequest: 3
});

//usage in request
$.ajax({
    url: '/echo/html/',
    success: function(data) {
        requestCallback.addCallbackToQueue(true, function() {
            alert('Im the first callback');
        });
    }
});
$.ajax({
    url: '/echo/html/',
    success: function(data) {
        requestCallback.addCallbackToQueue(true, function() {
            alert('Im the second callback');
        });
    }
});
$.ajax({
    url: '/echo/html/',
    success: function(data) {
        requestCallback.addCallbackToQueue(true, function() {
            alert('Im the third callback');
        });
    }
});

[The Code]

(代码)

var MyRequestsCompleted = (function() {
    var numRequestToComplete, requestsCompleted, callBacks, singleCallBack;

    return function(options) {
        if (!options) options = {};

        numRequestToComplete = options.numRequest || 0;
        requestsCompleted = options.requestsCompleted || 0;
        callBacks = [];
        var fireCallbacks = function() {
            alert("we're all complete");
            for (var i = 0; i < callBacks.length; i++) callBacks[i]();
        };
        if (options.singleCallback) callBacks.push(options.singleCallback);

        this.addCallbackToQueue = function(isComplete, callback) {
            if (isComplete) requestsCompleted++;
            if (callback) callBacks.push(callback);
            if (requestsCompleted == numRequestToComplete) fireCallbacks();
        };
        this.requestComplete = function(isComplete) {
            if (isComplete) requestsCompleted++;
            if (requestsCompleted == numRequestToComplete) fireCallbacks();
        };
        this.setCallback = function(callback) {
            callBacks.push(callBack);
        };
    };
})();

#2


134  

Looks like you've got some answers to this, however I think there is something worth mentioning here that will greatly simplify your code. jQuery introduced the $.when in v1.5. It looks like:

看起来您已经得到了一些答案,但是我认为这里有一些值得提及的内容可以极大地简化您的代码。jQuery介绍了美元。当在v1.5中。它看起来像:

$.when($.ajax(...), $.ajax(...)).then(function (resp1, resp2) {
    //this callback will be fired once all ajax calls have finished.
});

Didn't see it mentioned here, hope it helps.

这里没有提到,希望它有帮助。

#3


8  

Not seeing the need for any object malarky myself. Simple have a variable which is an integer. When you start a request, increment the number. When one completes, decrement it. When it's zero, there are no requests in progress, so you're done.

我自己也看不出需要什么东西。Simple有一个变量,它是一个整数。当您启动一个请求时,增加这个数字。当一个人完成了,就会减少它。当它为零的时候,没有请求在进行中,所以您已经完成了。

$('#button').click(function() {
    var inProgress = 0;

    function handleBefore() {
        inProgress++;
    };

    function handleComplete() {
        if (!--inProgress) {
            // do what's in here when all requests have completed.
        }
    };

    $.ajax({
        beforeSend: handleBefore,
        complete: function () {
            // whatever
            handleComplete();
            // whatever
        }
    });
    $.ajax({
        beforeSend: handleBefore,
        complete: function () {
            // whatever
            handleComplete();
            // whatever
        }
    });
    $.ajax({
        beforeSend: handleBefore,
        complete: function () {
            // whatever
            handleComplete();
            // whatever
        }
    });
});

#4


7  

It's worth noting that since $.when expects all of the ajax requests as sequential arguments (not an array) you'll commonly see $.when used with .apply() like so:

值得注意的是,从$开始。当将所有ajax请求预期为顺序参数(而不是数组)时,您通常会看到$。与。apply()类似:

// Save all requests in an array of jqXHR objects
var requests = arrayOfThings.map(function(thing) {
    return $.ajax({
        method: 'GET',
        url: 'thing/' + thing.id
    });
});
$.when.apply(this, requests).then(function(resp1, resp2/*, ... */) {
    // Each argument is an array with the following structure: [ data, statusText, jqXHR ]
    var responseArgsArray = Array.prototype.slice.call(this, arguments);

});

This is because $.when accepts args like this

这是因为美元。当接受这样的args

$.when(ajaxRequest1, ajaxRequest2, ajaxRequest3);

And not like this:

而不是像这样:

$.when([ajaxRequest1, ajaxRequest2, ajaxRequest3]);

#5


3  

EDIT -- perhaps the best option would be to create a service endpoint that does everything the three requests do. That way you only have to do one request, and all the data is where you need it to be in the response. If you find you are doing the same 3 requests over and over again, you will probably want to go this route. It is often a good design decision to set up a facade service on the server that lumps commonly used smaller server actions together. Just an idea.

编辑——也许最好的选择是创建一个服务端点,它可以完成三个请求所做的所有工作。这样你只需要做一个请求,所有的数据就是你需要它在响应中的位置。如果你发现你一遍又一遍地做同样的3个请求,你可能会想走这条路。在服务器上设置facade服务通常是一个很好的设计决策,而这些服务通常会一起使用较小的服务器操作。只是一个想法。


one way to do it would be to create a 'sync' object in your click handler before the ajax calls. Something like

一种方法是在ajax调用之前在单击处理程序中创建一个“sync”对象。类似的

var sync = {
   count: 0
}

The sync will be bound to the scope of the success calls automatically (closure). In the success handler, you increment the count, and if it is 3 you can call the other function.

同步将被自动绑定到成功调用的范围(闭包)。在成功处理程序中,增加计数,如果是3,可以调用另一个函数。

Alternatively, you could do something like

或者,您可以做类似的事情

var sync = {
   success1Complete: false,
   ...
   success3Complete: false,
}

when each success is executed, it would change the value in the sync to true. You would have to check the sync to make sure that all three are true before proceeding.

当执行每个成功时,它将同步中的值更改为true。在继续之前,您必须检查同步以确保这三个都是正确的。

Note the case where one of your xhrs does not return success -- you need to account for that.

请注意,如果您的某个xhrs没有返回成功——您需要对此进行说明。

Yet another option would be to always call the final function in your success handlers, and have it access the sync option to determine whether to actually do anything. You would need to make sure the sync is in the scope of that function though.

另一个选项是始终调用成功处理程序中的最终函数,并让它访问sync选项,以确定是否实际执行任何操作。您需要确保同步在该函数的范围内。

#6


3  

I like hvgotcodes' idea. My suggestion is to add a generic incrementer that compares the number complete to the number needed and then runs the final callback. This could be built into the final callback.

我喜欢hvgotcodes的主意。我的建议是添加一个通用的incrementer,将这个数字与所需的数量进行比较,然后运行最终的回调。这可以内置到最终回调中。

var sync = {
 callbacksToComplete = 3,
 callbacksCompleted = 0,
 addCallbackInstance = function(){
  this.callbacksCompleted++;
  if(callbacksCompleted == callbacksToComplete) {
   doFinalCallBack();
  }
 }
};

[Edited to reflect name updates.]

[编辑以反映姓名更新]

#7


0  

I asked the same question a while ago and got a couple of good answers here: Best way to add a 'callback' after a series of asynchronous XHR calls

不久前我也问了同样的问题,得到了一些很好的答案:在一系列异步XHR调用之后添加回调的最佳方式

#8


0  

I got some good hints from the answers on this page. I adapted it a bit for my use and thought I could share.

我从这一页的答案中得到了一些很好的提示。我对它进行了一些调整,以供我使用,并认为我可以分享。

// lets say we have 2 ajax functions that needs to be "synchronized". 
// In other words, we want to know when both are completed.
function foo1(callback) {
    $.ajax({
        url: '/echo/html/',
        success: function(data) {
            alert('foo1');
            callback();               
        }
    });
}

function foo2(callback) {
    $.ajax({
        url: '/echo/html/',
        success: function(data) {
            alert('foo2');
            callback();
        }
    });
}

// here is my simplified solution
ajaxSynchronizer = function() {
    var funcs = [];
    var funcsCompleted = 0;
    var callback;

    this.add = function(f) {
        funcs.push(f);
    }

    this.synchronizer = function() {
        funcsCompleted++;
        if (funcsCompleted == funcs.length) {
            callback.call(this);
        }
    }

    this.callWhenFinished = function(cb) {
        callback = cb;
        for (var i = 0; i < funcs.length; i++) {
            funcs[i].call(this, this.synchronizer);
        }
    }
}

// this is the function that is called when both ajax calls are completed.
afterFunction = function() {
    alert('All done!');
}

// this is how you set it up
var synchronizer = new ajaxSynchronizer();
synchronizer.add(foo1);
synchronizer.add(foo2);
synchronizer.callWhenFinished(afterFunction);

There are some limitations here, but for my case it was ok. I also found that for more advanced stuff it there is also a AOP plugin (for jQuery) that might be useful: http://code.google.com/p/jquery-aop/

这里有一些限制,但对我来说没有问题。我还发现,对于更高级的东西,还有一个AOP插件(用于jQuery)可能有用:http://code.google.com/p/jquery-aop/

#9


0  

I came across this problem today, and this was my naive attempt before watching the accepted answer.

我今天遇到了这个问题,这是我在看到公认答案之前的天真尝试。

<script>
    function main() {
        var a, b, c
        var one = function() {
            if ( a != undefined  && b != undefined && c != undefined ) {
                alert("Ok")
            } else {
                alert( "¬¬ ")
            }
        }

        fakeAjaxCall( function() {
            a = "two"
            one()
        } )
        fakeAjaxCall( function() {
            b = "three"
            one()
        } )
        fakeAjaxCall( function() {
            c = "four"
            one()
        } )
    }
    function fakeAjaxCall( a ) {
        a()
    }
    main()
</script>

#10


0  

It's not jquery (and it appears jquery has a workable solution) but just as another option....

这不是jquery和jquery似乎有一个可行的解决方案,但就像另一个选项....

I've had similar problems working heavily with SharePoint web services - you often need to pull data from multiple sources to generate input for a single process.

我在SharePoint web服务上也遇到过类似的问题——您通常需要从多个源中提取数据来为单个进程生成输入。

To solve it I embedded this kind of functionality into my AJAX abstraction library. You can easily define a request which will trigger a set of handlers when complete. However each request can be defined with multiple http calls. Here's the component (and detailed documentation):

为了解决这个问题,我将这种功能嵌入到我的AJAX抽象库中。您可以轻松地定义一个请求,该请求将在完成时触发一组处理程序。但是每个请求都可以通过多个http调用来定义。以下是组件(和详细文档):

DPAJAX at DepressedPress.com

DPAJAX DepressedPress.com

This simple example creates one request with three calls and then passes that information, in the call order, to a single handler:

这个简单的示例创建一个有三个调用的请求,然后按调用顺序将该信息传递给单个处理程序:

    // The handler function 
function AddUp(Nums) { alert(Nums[1] + Nums[2] + Nums[3]) }; 

    // Create the pool 
myPool = DP_AJAX.createPool(); 

    // Create the request 
myRequest = DP_AJAX.createRequest(AddUp); 

    // Add the calls to the request 
myRequest.addCall("GET", "http://www.mysite.com/Add.htm", [5,10]); 
myRequest.addCall("GET", "http://www.mysite.com/Add.htm", [4,6]); 
myRequest.addCall("GET", "http://www.mysite.com/Add.htm", [7,13]); 

    // Add the request to the pool 
myPool.addRequest(myRequest); 

Note that unlike many of the other solutions (including, I believe the "when" solution in jquery) provided this method does not force single threading of the calls being made - each will still run as quickly (or as slowly) as the environment allows but the single handler will only be called when all are complete. It also supports the setting of timeout values and retry attempts if your service is a little flakey.

注意,不像其他的许多解决方案(包括,我相信“当”解决方案在jquery)提供这种方法不力单线程的调用,每个仍将运行尽快(或缓慢)作为环境允许但单处理程序时只会调用都是完整的。它还支持设置超时值和重试尝试(如果您的服务有点不稳定)。

I've found it insanely useful (and incredibly simple to understand from a code perspective). No more chaining, no more counting calls and saving output. Just "set it and forget it".

我发现它非常有用(从代码的角度理解它非常简单)。不再有链接,不再有计数调用和保存输出。只要“设置它,然后忘记它”。

#11


-1  

async   : false,

By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active. As of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated; you must use the success/error/complete callback options instead of the corresponding methods of the jqXHR object such as jqXHR.done() or the deprecated jqXHR.success().

默认情况下,所有请求都是异步发送的(也就是说,默认情况下将其设置为true)。如果需要同步请求,请将此选项设置为false。跨域请求和数据类型:“jsonp”请求不支持同步操作。注意,同步请求可以临时锁定浏览器,在请求处于活动状态时禁用任何操作。对于jQuery 1.8,不赞成在jqXHR ($.Deferred)中使用async: false;您必须使用success/error/complete回调选项,而不是jqXHR对象(如jqXHR.done()或已弃用的jqXHR.success())的相应方法。

#12


-2  

$.ajax({type:'POST', url:'www.naver.com', dataType:'text', async:false,
    complete:function(xhr, textStatus){},
    error:function(xhr, textStatus){},
    success:function( data ){
        $.ajax({type:'POST', 
            ....
            ....
            success:function(data){
                $.ajax({type:'POST',
                    ....
                    ....
            }
        }
    });

I'm sorry but I can't explain what I worte cuz I'm a Korean who can't speak even a word in english. but I think you can easily understand it.

对不起,我不能解释我写的东西,因为我是韩国人,连一个英文单词都不会说。但我认为你很容易理解。

#1


93  

Here is a callback object I wrote where you can either set a single callback to fire once all complete or let each have their own callback and fire them all once all complete:

这里是我写的一个回调对象,您可以设置一个回调,在全部完成后触发,或者让每个回调都有自己的回调,并在全部完成后触发:

NOTICE

请注意

Since jQuery 1.5+ you can use the deferred method as described in another answer:

由于jQuery 1.5+可以使用另一个答案中描述的deferred方法:

  $.when($.ajax(), [...]).then(function(results){},[...]);

Example of deferred here

递延的例子在这里

for jQuery < 1.5 the following will work or if you need to have your ajax calls fired at unknown times as shown here with two buttons: fired after both buttons are clicked

对于jQuery < 1.5,以下方法将有效,或者如果您需要在未知的时间触发ajax调用,如下所示,其中有两个按钮:单击两个按钮后触发

[usage]

(使用)

for single callback once complete: Working Example

对于一次完成的回调:工作示例

// initialize here
var requestCallback = new MyRequestsCompleted({
    numRequest: 3,
    singleCallback: function(){
        alert( "I'm the callback");
    }
});

//usage in request
$.ajax({
    url: '/echo/html/',
    success: function(data) {
        requestCallback.requestComplete(true);
    }
});
$.ajax({
    url: '/echo/html/',
    success: function(data) {
        requestCallback.requestComplete(true);
    }
});
$.ajax({
    url: '/echo/html/',
    success: function(data) {
        requestCallback.requestComplete(true);
    }
});

each having their own callback when all complete: Working Example

当全部完成时,每个都有自己的回调:工作示例

//initialize 
var requestCallback = new MyRequestsCompleted({
    numRequest: 3
});

//usage in request
$.ajax({
    url: '/echo/html/',
    success: function(data) {
        requestCallback.addCallbackToQueue(true, function() {
            alert('Im the first callback');
        });
    }
});
$.ajax({
    url: '/echo/html/',
    success: function(data) {
        requestCallback.addCallbackToQueue(true, function() {
            alert('Im the second callback');
        });
    }
});
$.ajax({
    url: '/echo/html/',
    success: function(data) {
        requestCallback.addCallbackToQueue(true, function() {
            alert('Im the third callback');
        });
    }
});

[The Code]

(代码)

var MyRequestsCompleted = (function() {
    var numRequestToComplete, requestsCompleted, callBacks, singleCallBack;

    return function(options) {
        if (!options) options = {};

        numRequestToComplete = options.numRequest || 0;
        requestsCompleted = options.requestsCompleted || 0;
        callBacks = [];
        var fireCallbacks = function() {
            alert("we're all complete");
            for (var i = 0; i < callBacks.length; i++) callBacks[i]();
        };
        if (options.singleCallback) callBacks.push(options.singleCallback);

        this.addCallbackToQueue = function(isComplete, callback) {
            if (isComplete) requestsCompleted++;
            if (callback) callBacks.push(callback);
            if (requestsCompleted == numRequestToComplete) fireCallbacks();
        };
        this.requestComplete = function(isComplete) {
            if (isComplete) requestsCompleted++;
            if (requestsCompleted == numRequestToComplete) fireCallbacks();
        };
        this.setCallback = function(callback) {
            callBacks.push(callBack);
        };
    };
})();

#2


134  

Looks like you've got some answers to this, however I think there is something worth mentioning here that will greatly simplify your code. jQuery introduced the $.when in v1.5. It looks like:

看起来您已经得到了一些答案,但是我认为这里有一些值得提及的内容可以极大地简化您的代码。jQuery介绍了美元。当在v1.5中。它看起来像:

$.when($.ajax(...), $.ajax(...)).then(function (resp1, resp2) {
    //this callback will be fired once all ajax calls have finished.
});

Didn't see it mentioned here, hope it helps.

这里没有提到,希望它有帮助。

#3


8  

Not seeing the need for any object malarky myself. Simple have a variable which is an integer. When you start a request, increment the number. When one completes, decrement it. When it's zero, there are no requests in progress, so you're done.

我自己也看不出需要什么东西。Simple有一个变量,它是一个整数。当您启动一个请求时,增加这个数字。当一个人完成了,就会减少它。当它为零的时候,没有请求在进行中,所以您已经完成了。

$('#button').click(function() {
    var inProgress = 0;

    function handleBefore() {
        inProgress++;
    };

    function handleComplete() {
        if (!--inProgress) {
            // do what's in here when all requests have completed.
        }
    };

    $.ajax({
        beforeSend: handleBefore,
        complete: function () {
            // whatever
            handleComplete();
            // whatever
        }
    });
    $.ajax({
        beforeSend: handleBefore,
        complete: function () {
            // whatever
            handleComplete();
            // whatever
        }
    });
    $.ajax({
        beforeSend: handleBefore,
        complete: function () {
            // whatever
            handleComplete();
            // whatever
        }
    });
});

#4


7  

It's worth noting that since $.when expects all of the ajax requests as sequential arguments (not an array) you'll commonly see $.when used with .apply() like so:

值得注意的是,从$开始。当将所有ajax请求预期为顺序参数(而不是数组)时,您通常会看到$。与。apply()类似:

// Save all requests in an array of jqXHR objects
var requests = arrayOfThings.map(function(thing) {
    return $.ajax({
        method: 'GET',
        url: 'thing/' + thing.id
    });
});
$.when.apply(this, requests).then(function(resp1, resp2/*, ... */) {
    // Each argument is an array with the following structure: [ data, statusText, jqXHR ]
    var responseArgsArray = Array.prototype.slice.call(this, arguments);

});

This is because $.when accepts args like this

这是因为美元。当接受这样的args

$.when(ajaxRequest1, ajaxRequest2, ajaxRequest3);

And not like this:

而不是像这样:

$.when([ajaxRequest1, ajaxRequest2, ajaxRequest3]);

#5


3  

EDIT -- perhaps the best option would be to create a service endpoint that does everything the three requests do. That way you only have to do one request, and all the data is where you need it to be in the response. If you find you are doing the same 3 requests over and over again, you will probably want to go this route. It is often a good design decision to set up a facade service on the server that lumps commonly used smaller server actions together. Just an idea.

编辑——也许最好的选择是创建一个服务端点,它可以完成三个请求所做的所有工作。这样你只需要做一个请求,所有的数据就是你需要它在响应中的位置。如果你发现你一遍又一遍地做同样的3个请求,你可能会想走这条路。在服务器上设置facade服务通常是一个很好的设计决策,而这些服务通常会一起使用较小的服务器操作。只是一个想法。


one way to do it would be to create a 'sync' object in your click handler before the ajax calls. Something like

一种方法是在ajax调用之前在单击处理程序中创建一个“sync”对象。类似的

var sync = {
   count: 0
}

The sync will be bound to the scope of the success calls automatically (closure). In the success handler, you increment the count, and if it is 3 you can call the other function.

同步将被自动绑定到成功调用的范围(闭包)。在成功处理程序中,增加计数,如果是3,可以调用另一个函数。

Alternatively, you could do something like

或者,您可以做类似的事情

var sync = {
   success1Complete: false,
   ...
   success3Complete: false,
}

when each success is executed, it would change the value in the sync to true. You would have to check the sync to make sure that all three are true before proceeding.

当执行每个成功时,它将同步中的值更改为true。在继续之前,您必须检查同步以确保这三个都是正确的。

Note the case where one of your xhrs does not return success -- you need to account for that.

请注意,如果您的某个xhrs没有返回成功——您需要对此进行说明。

Yet another option would be to always call the final function in your success handlers, and have it access the sync option to determine whether to actually do anything. You would need to make sure the sync is in the scope of that function though.

另一个选项是始终调用成功处理程序中的最终函数,并让它访问sync选项,以确定是否实际执行任何操作。您需要确保同步在该函数的范围内。

#6


3  

I like hvgotcodes' idea. My suggestion is to add a generic incrementer that compares the number complete to the number needed and then runs the final callback. This could be built into the final callback.

我喜欢hvgotcodes的主意。我的建议是添加一个通用的incrementer,将这个数字与所需的数量进行比较,然后运行最终的回调。这可以内置到最终回调中。

var sync = {
 callbacksToComplete = 3,
 callbacksCompleted = 0,
 addCallbackInstance = function(){
  this.callbacksCompleted++;
  if(callbacksCompleted == callbacksToComplete) {
   doFinalCallBack();
  }
 }
};

[Edited to reflect name updates.]

[编辑以反映姓名更新]

#7


0  

I asked the same question a while ago and got a couple of good answers here: Best way to add a 'callback' after a series of asynchronous XHR calls

不久前我也问了同样的问题,得到了一些很好的答案:在一系列异步XHR调用之后添加回调的最佳方式

#8


0  

I got some good hints from the answers on this page. I adapted it a bit for my use and thought I could share.

我从这一页的答案中得到了一些很好的提示。我对它进行了一些调整,以供我使用,并认为我可以分享。

// lets say we have 2 ajax functions that needs to be "synchronized". 
// In other words, we want to know when both are completed.
function foo1(callback) {
    $.ajax({
        url: '/echo/html/',
        success: function(data) {
            alert('foo1');
            callback();               
        }
    });
}

function foo2(callback) {
    $.ajax({
        url: '/echo/html/',
        success: function(data) {
            alert('foo2');
            callback();
        }
    });
}

// here is my simplified solution
ajaxSynchronizer = function() {
    var funcs = [];
    var funcsCompleted = 0;
    var callback;

    this.add = function(f) {
        funcs.push(f);
    }

    this.synchronizer = function() {
        funcsCompleted++;
        if (funcsCompleted == funcs.length) {
            callback.call(this);
        }
    }

    this.callWhenFinished = function(cb) {
        callback = cb;
        for (var i = 0; i < funcs.length; i++) {
            funcs[i].call(this, this.synchronizer);
        }
    }
}

// this is the function that is called when both ajax calls are completed.
afterFunction = function() {
    alert('All done!');
}

// this is how you set it up
var synchronizer = new ajaxSynchronizer();
synchronizer.add(foo1);
synchronizer.add(foo2);
synchronizer.callWhenFinished(afterFunction);

There are some limitations here, but for my case it was ok. I also found that for more advanced stuff it there is also a AOP plugin (for jQuery) that might be useful: http://code.google.com/p/jquery-aop/

这里有一些限制,但对我来说没有问题。我还发现,对于更高级的东西,还有一个AOP插件(用于jQuery)可能有用:http://code.google.com/p/jquery-aop/

#9


0  

I came across this problem today, and this was my naive attempt before watching the accepted answer.

我今天遇到了这个问题,这是我在看到公认答案之前的天真尝试。

<script>
    function main() {
        var a, b, c
        var one = function() {
            if ( a != undefined  && b != undefined && c != undefined ) {
                alert("Ok")
            } else {
                alert( "¬¬ ")
            }
        }

        fakeAjaxCall( function() {
            a = "two"
            one()
        } )
        fakeAjaxCall( function() {
            b = "three"
            one()
        } )
        fakeAjaxCall( function() {
            c = "four"
            one()
        } )
    }
    function fakeAjaxCall( a ) {
        a()
    }
    main()
</script>

#10


0  

It's not jquery (and it appears jquery has a workable solution) but just as another option....

这不是jquery和jquery似乎有一个可行的解决方案,但就像另一个选项....

I've had similar problems working heavily with SharePoint web services - you often need to pull data from multiple sources to generate input for a single process.

我在SharePoint web服务上也遇到过类似的问题——您通常需要从多个源中提取数据来为单个进程生成输入。

To solve it I embedded this kind of functionality into my AJAX abstraction library. You can easily define a request which will trigger a set of handlers when complete. However each request can be defined with multiple http calls. Here's the component (and detailed documentation):

为了解决这个问题,我将这种功能嵌入到我的AJAX抽象库中。您可以轻松地定义一个请求,该请求将在完成时触发一组处理程序。但是每个请求都可以通过多个http调用来定义。以下是组件(和详细文档):

DPAJAX at DepressedPress.com

DPAJAX DepressedPress.com

This simple example creates one request with three calls and then passes that information, in the call order, to a single handler:

这个简单的示例创建一个有三个调用的请求,然后按调用顺序将该信息传递给单个处理程序:

    // The handler function 
function AddUp(Nums) { alert(Nums[1] + Nums[2] + Nums[3]) }; 

    // Create the pool 
myPool = DP_AJAX.createPool(); 

    // Create the request 
myRequest = DP_AJAX.createRequest(AddUp); 

    // Add the calls to the request 
myRequest.addCall("GET", "http://www.mysite.com/Add.htm", [5,10]); 
myRequest.addCall("GET", "http://www.mysite.com/Add.htm", [4,6]); 
myRequest.addCall("GET", "http://www.mysite.com/Add.htm", [7,13]); 

    // Add the request to the pool 
myPool.addRequest(myRequest); 

Note that unlike many of the other solutions (including, I believe the "when" solution in jquery) provided this method does not force single threading of the calls being made - each will still run as quickly (or as slowly) as the environment allows but the single handler will only be called when all are complete. It also supports the setting of timeout values and retry attempts if your service is a little flakey.

注意,不像其他的许多解决方案(包括,我相信“当”解决方案在jquery)提供这种方法不力单线程的调用,每个仍将运行尽快(或缓慢)作为环境允许但单处理程序时只会调用都是完整的。它还支持设置超时值和重试尝试(如果您的服务有点不稳定)。

I've found it insanely useful (and incredibly simple to understand from a code perspective). No more chaining, no more counting calls and saving output. Just "set it and forget it".

我发现它非常有用(从代码的角度理解它非常简单)。不再有链接,不再有计数调用和保存输出。只要“设置它,然后忘记它”。

#11


-1  

async   : false,

By default, all requests are sent asynchronously (i.e. this is set to true by default). If you need synchronous requests, set this option to false. Cross-domain requests and dataType: "jsonp" requests do not support synchronous operation. Note that synchronous requests may temporarily lock the browser, disabling any actions while the request is active. As of jQuery 1.8, the use of async: false with jqXHR ($.Deferred) is deprecated; you must use the success/error/complete callback options instead of the corresponding methods of the jqXHR object such as jqXHR.done() or the deprecated jqXHR.success().

默认情况下,所有请求都是异步发送的(也就是说,默认情况下将其设置为true)。如果需要同步请求,请将此选项设置为false。跨域请求和数据类型:“jsonp”请求不支持同步操作。注意,同步请求可以临时锁定浏览器,在请求处于活动状态时禁用任何操作。对于jQuery 1.8,不赞成在jqXHR ($.Deferred)中使用async: false;您必须使用success/error/complete回调选项,而不是jqXHR对象(如jqXHR.done()或已弃用的jqXHR.success())的相应方法。

#12


-2  

$.ajax({type:'POST', url:'www.naver.com', dataType:'text', async:false,
    complete:function(xhr, textStatus){},
    error:function(xhr, textStatus){},
    success:function( data ){
        $.ajax({type:'POST', 
            ....
            ....
            success:function(data){
                $.ajax({type:'POST',
                    ....
                    ....
            }
        }
    });

I'm sorry but I can't explain what I worte cuz I'm a Korean who can't speak even a word in english. but I think you can easily understand it.

对不起,我不能解释我写的东西,因为我是韩国人,连一个英文单词都不会说。但我认为你很容易理解。