jQuery的多个Ajax调用回调

我想在点击事件中做三个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*/}); }); 

这里是我写的一个回调对象,你可以设置一个回调,一旦完成所有的回调,或者让每个回调都有自己的回调,并且一旦完成就全部激活:

注意

由于jQuery 1.5+可以使用延迟方法,如另一个答案中所述:

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

这里推迟的例子

对于jQuery <1.5,以下内容可以正常工作,或者如果您需要在未知时间触发ajax调用,如下所示,使用两个按钮: 点击两个按钮后触发

[用法]

单次回调一次完成: 工作示例

 // 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); } }); 

每个完成时都有各自的回调: 工作示例

 //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'); }); } }); 

[代码]

 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); }; }; })(); 

看起来你已经得到了一些答案,但是我认为在这里值得一提的是,这将大大简化你的代码。 jQuery在v1.5中引入了$.when 。 看起来像:

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

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

没有看到任何对象malarky我自己的需要。 简单的有一个整数的变量。 当你开始一个请求时,增加这个数字。 当一个完成时,减少它。 当它为零时,没有正在进行的请求,所以你完成了。

 $('#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 } }); }); 

编辑 – 也许最好的选择是创建一个服务端点,完成这三个请求所做的一切。 这样你只需要做一个请求,所有的数据就是你需要的地方。 如果你发现你一遍又一遍地做同样的三个请求,你可能会想要走这条路。 在服务器上设置一个门面服务通常是一个很好的设计决策,将常用的小型服务器操作集中在一起。 只是一个想法。


一种方法是在ajax调用之前在你的点击处理程序中创建一个“同步”对象。 就像是

 var sync = { count: 0 } 

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

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

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

当每个成功执行时,它会将同步中的值更改为true。 你必须检查同步,以确保所有三个都是真实的,然后再继续。

注意你的一个xhrs没有返回成功的情况 – 你需要说明这一点。

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

我喜欢hvgotcodes的想法。 我的建议是添加一个通用的增量器,将完成的数字与需要的数字进行比较,然后运行最终的回调。 这可以被建成最后的回调。

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

[编辑以反映名称更新。]

值得注意的是,自$.when期望所有的ajax请求作为顺序参数(而不是数组)时,您通常会在使用.apply()看到$.when

 // 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); }); 

这是因为$.when接受这样的参数

 $.when(ajaxRequest1, ajaxRequest2, ajaxRequest3); 

而不是这样的:

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

我刚才问同样的问题,在这里得到了一些很好的答案: 在一系列异步XHR调用之后添加“回调”的最佳方法

我从这个页面的答案中得到了一些很好的提示。 我改编了一下,以为我可以分享。

 // 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); 

这里有一些限制,但对于我的情况是好的。 我还发现,对于更高级的东西,它也有一个AOP插件(用于jQuery),可能是有用的: http : //code.google.com/p/jquery-aop/

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

 <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> 

这不是jQuery(和似乎jQuery有一个可行的解决方案),但只是另一种选择….

我有类似的问题与SharePoint Web服务密切相关 – 您经常需要从多个来源获取数据以为单个进程生成输入。

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

DPAJAX在DepressedPress.com

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

  // 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); 

请注意,与许多其他解决方案(包括,我相信jquery中的“何时”解决方案)提供的这种方法不强制进行单线程的调用 – 每个将仍然运行尽可能快(或缓慢),因为环境允许但是只有当所有的处理完成时才会调用这个处理程序。 它也支持设置超时值和重试尝试,如果你的服务是一个小小的flakey。

我发现它非常有用(从代码的角度来看,这非常简单)。 没有更多的链接,不再计数电话和节省输出。 只是“设置它,忘记它”。

 async : false, 

默认情况下,所有请求都是异步发送的(即默认设置为true)。 如果您需要同步请求,请将此选项设置为false 。 跨域请求和dataType: "jsonp"请求不支持同步操作。 请注意,同步请求可能会暂时锁定浏览器,并在请求处于活动状态时禁用任何操作。 从jQuery 1.8开始 ,不赞成使用带有jqXHR$.Deferred )的async: false ; 您必须使用成功/错误/完整回调选项,而不是jqXHR对象的相应方法(如jqXHR.done()或不赞成使用的jqXHR.success()

 $.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', .... .... } } }); 

我很抱歉,但我不能解释我是什么,因为我是一个韩语,甚至不会说一个英文单词。 但我认为你可以很容易地理解它。

Interesting Posts