假设我有一个事件处理程序,它对服务器进行两次AJAX调用:
$("#foo").click(function(){
$.get("bar", function(){ alert("Hello"); });
$.get("baz", function(){ alert("World"); });
});
我意识到调用回调的顺序是不确定的,因为它取决于每个请求需要多长时间等等。
但是这是我的问题:是否保证在调用任何一个回调函数之前我将到达事件处理程序的末尾?我已经读过一个页面的所有Javascript都在一个线程中执行,所以我认为这意味着我可以保证在调用任何回调之前完成我的click
事件处理程序。
这是对的吗?或者第一个请求是否可能完成并且在我们甚至到达事件处理程序结束之前执行了第一个回调?
答案 0 :(得分:11)
是的,这是有保证的,你是对的 - 只有一个线程(暂时忽略web-worker)。当一段JavaScript代码执行(占用执行线程)并且AJAX回调到达(或任何其他GUI事件,超时等)时,它会排队等待,直到执行线程空闲(当前代码完成)。 / p>
JavaScript引擎永远不会中断正在运行的代码来处理传入事件 - 事件将始终在队列中轻轻等待。这就是为什么在执行CPU密集型代码时GUI似乎冻结的原因 - 没有处理任何事件。这也是同步AJAX请求不好的原因。
答案 1 :(得分:4)
是的,JavaScript是单线程的,因此您的执行永远不会被抢占。
异步回调和事件的工作方式相同;您mousedown
的处理程序保证在mouseup
的处理程序之前完成,即使您的mousedown
处理程序需要2秒钟并且您让鼠标立即执行。
对于AJAX回调也是如此,它被放入与等待处理的事件相同的(类型)队列中
答案 2 :(得分:1)
一个有趣的转折是代替$ .get(),假设我们使用的是从其他地方获得的承诺(即实际的异步调用是在其他地方进行的)( - 为什么我们会遇到这样的情况?好吧,也许我们有一个memoized查询功能。)
现在,如果有人使用jQuery promises,如果已经解决,则会同步调用回调。这是一个问题吗?那取决于你的要求。如果是,那么你可以将回调代码包装在 setTimeout(cb,0)中。
另一方面,如果您希望回调被抢占怎么办?见my examples here
答案 3 :(得分:0)
我意识到调用回调的顺序是不确定的,因为它取决于每个请求需要多长时间等等。
你写的方式是肯定的..但是有办法组织和控制这个......即deffereds和promises。
以下是一个很好的概述:http://net.tutsplus.com/tutorials/javascript-ajax/wrangle-async-tasks-with-jquery-promises/
正确使用它们将确保您不会遇到您似乎试图避免的任何问题。
** 正如@Juan指出的那样,这不是你提出的问题的黑白答案。我只是想指出您在不同的方向或方式来查看同一个问题,以便您可以更明确地定义您的预期行为。