问题 事件处理程序是否可以在调用AJAX回调之前完成?


假设我有一个事件处理程序,它对服务器进行两次AJAX调用:

$("#foo").click(function(){ 
    $.get("bar", function(){ alert("Hello"); });
    $.get("baz", function(){ alert("World"); });
});

我意识到调用回调的顺序是不确定的,因为它取决于每个请求需要多长时间等。

但这是我的问题:是否保证在调用任何一个回调函数之前我将到达事件处理程序的末尾?我已经读过一个页面的所有Javascript都在一个线程中执行,所以我认为这意味着我的 click 保证在调用任何回调之前完成事件处理程序。

它是否正确?或者第一个请求是否可能完成并且在我们甚至到达事件处理程序结束之前执行了第一个回调?


12623
2018-04-03 18:19


起源



答案:


是的,这是有保证的,你是对的 - 只有一个线程(忽略 s暂时)。当一段JavaScript代码执行(占用执行线程)并且AJAX回调到达(或任何其他GUI事件,超时等)时,它会排队等待,直到执行线程空闲(当前代码完成)。

JavaScript引擎永远不会中断正在运行的代码来处理传入事件 - 事件将始终在队列中轻轻等待。这就是为什么在执行CPU密集型代码时GUI似乎冻结的原因 - 没有处理任何事件。这也是同步AJAX请求不好的原因。

也可以看看


11
2018-04-03 18:22





是的,JavaScript是单线程的,因此您的执行永远不会被抢占。

异步回调和事件的工作方式相同;你的处理程序 mousedown 保证在你的处理程序之前完成 mouseup,即使你的 mousedown 处理程序需要2秒钟,你让鼠标立即进入。

对于AJAX回调也是如此,它被放入与等待处理的事件相同的(类型)队列中


4
2018-04-03 18:21





一个有趣的转折是代替$ .get(),假设我们使用的是我们从其他地方获得的承诺(即实际的异步调用是在其他地方进行的)( - 为什么我们会有这样的情况?好吧也许我们有一个memoized查询功能。)

现在,如果一个人正在使用jQuery promises,那么如果已经解决,则会同步调用回调。这是一个问题吗?那取决于你的要求。如果是,那么你可以将回调代码包装在一个 setTimeout(cb,0)。

另一方面,如果你想要回调被抢先怎么办?看到 我的例子在这里


1
2018-04-25 00:18



@Juan Mendes,我可能会被指责没有真正回答这个问题:-( - Ustaman Sangat


答案:


是的,这是有保证的,你是对的 - 只有一个线程(忽略 s暂时)。当一段JavaScript代码执行(占用执行线程)并且AJAX回调到达(或任何其他GUI事件,超时等)时,它会排队等待,直到执行线程空闲(当前代码完成)。

JavaScript引擎永远不会中断正在运行的代码来处理传入事件 - 事件将始终在队列中轻轻等待。这就是为什么在执行CPU密集型代码时GUI似乎冻结的原因 - 没有处理任何事件。这也是同步AJAX请求不好的原因。

也可以看看


11
2018-04-03 18:22





是的,JavaScript是单线程的,因此您的执行永远不会被抢占。

异步回调和事件的工作方式相同;你的处理程序 mousedown 保证在你的处理程序之前完成 mouseup,即使你的 mousedown 处理程序需要2秒钟,你让鼠标立即进入。

对于AJAX回调也是如此,它被放入与等待处理的事件相同的(类型)队列中


4
2018-04-03 18:21





一个有趣的转折是代替$ .get(),假设我们使用的是我们从其他地方获得的承诺(即实际的异步调用是在其他地方进行的)( - 为什么我们会有这样的情况?好吧也许我们有一个memoized查询功能。)

现在,如果一个人正在使用jQuery promises,那么如果已经解决,则会同步调用回调。这是一个问题吗?那取决于你的要求。如果是,那么你可以将回调代码包装在一个 setTimeout(cb,0)。

另一方面,如果你想要回调被抢先怎么办?看到 我的例子在这里


1
2018-04-25 00:18



@Juan Mendes,我可能会被指责没有真正回答这个问题:-( - Ustaman Sangat


我意识到调用回调的顺序是不确定的,因为它取决于每个请求需要多长时间等。

在你编写它的方式是的..但有一些方法来组织和控制这个...即deffereds和promises。

这是一个很好的概述: http://net.tutsplus.com/tutorials/javascript-ajax/wrangle-async-tasks-with-jquery-promises/

正确使用它们将确保您不会遇到您似乎试图避免的任何问题。

** 正如@Juan指出的那样,这不是你问的问题的黑白答案。我只是想指出你在不同的方向或方法来查看同一个问题,这样你就可以更明确地定义你的预期行为。


0
2018-04-03 19:10



OP并不是要求异步任务无序返回 - Juan Mendes
不,他不是,但我说如果他控制所有他的异步回调,他可能不会遇到他试图首先避免的问题。这似乎是关于确保处理程序在其他处理程序之前完成。 - Patrick Scott
我可能会过度分析他的问题,并提供解决我从他的问题中隐含的问题,但他可能只是好奇。 - Patrick Scott
问题是:click处理程序触发一个AJAX请求,是否有可能在单击处理程序完成之前调用成功回调?它不是跟踪/争论异步任务。你所说的是有道理的,但由于它并没有真正回答这个问题,因此更有可能混淆OP - Juan Mendes
而不是确保以正确的顺序编写代码,以便处理程序在正确的时间发送到事件队列,这样一切都可以发生而不会破坏..只是试图指出他在正确的方向,使事情更容易处理在第一地点。 :)虽然我确实看到了你的观点 - Patrick Scott