2011-05-20 41 views
0

通常,我会使用传递给'jQuery.getJSON'函数的回调函数在服务器响应后执行某些操作。在这种情况下,我在某些输入元素上应用了事件处理程序,但这些处理程序只应在多个Ajax请求成功后才执行。基本上我需要暂停事件处理程序的执行,直到我期望的某些数据可用。如何同步JavaScript代码,这取决于多个Ajax请求的响应?

在多线程语言中,我会使用互斥锁/信号量来做到这一点,但由于JavaScript是单线程的,我不知道这样的事情是否可能。

回答

1

一个手动的方式来做到这一点是要排队的AJAX数组中的调用,然后计算您收到的回复的数量,并等待该计数与原始队列的大小相匹配(或者,在响应完成时将呼叫从队列中弹出,并且您知道在队列大小为0)。

你将不得不检查你是否准备好继续setTimeout调用。

或者,您可以在jQuery的退房递延支持1.5+

编辑:手动方法的快速和肮脏的例子:

var remoteCallA = function(){ 
    $.getJSON('someurl', function(){ 
     success++; 
    }); 
}; 

var remoteCallB = function(){ 
    // etc 
}; 

var whenAllDone = function(){ 
    // do something when everything is done 
}; 

var checkAllDone = function(){ 
    if(success === remoteCalls.length){ 
     whenAllDone(); 
    } 
    else{ 
     setTimeout(checkAllDone, 1000); 
    } 
}; 

var remoteCalls = [remoteCallA, remoteCallB]; 
var success = 0; 
for(var i = 0, length = remoteCalls.length; i++){ 
    remoteCalls[i](); 
} 

checkAllDone(); 
+0

嗯,我感兴趣的'setTimeout'功能可能是我需要的。在你给出的例子中,假设你使用了一个小超时(比如20毫秒),这个递归会不会变得太深?它可能会导致堆栈溢出。 – 2011-05-20 18:28:58

+0

@Thiado这实际上并不是递归,因为setTimeout()的调用会立即返回并退出函数。它只是告诉浏览器'嘿,在1000毫秒内运行'。 – Matt 2011-05-20 18:30:28

+0

谢谢你,这正是我需要的:) – 2011-05-20 18:33:03

1

javascript是基于事件的,所以一种方法是在每次协调xhr得到响应时抛出一个事件。事件处理程序跟踪响应,并且只有在全部返回时才会继续。

或者你也可以做同样的事情,而不活动,只要直接调用的方法和协调在那里的答复....

1

我可以给你一个肮脏的解决方案。一旦所有查询返回,创建你想要执行的函数。创建另一个函数来执行调度。就像信号/互斥一样,创建一个“同步”变量。增加每个呼叫的变量。然后,在调度函数中,递减变量,如果为零,则执行所需的函数。将调度函数应用为ajax返回的事件处理程序(如果您已有处理程序,而您不需要要暂停,请将其放在每个现有处理程序的末尾)。

然后,想一个更优雅的解决方案。