是否在Javascript中按顺序执行相同的超时?

jkl*_*jkl 26 javascript operator-precedence settimeout

假设我这样做

setTimeout(foo, 0);

...

setTimeout(bar, 0);
Run Code Online (Sandbox Code Playgroud)

我可以确定foo会在开始执行之前吗?如果不是0,我会使用1,10或100的超时来表示条形码?

简单的实验表明,在超时值相等的情况下,超时目标的执行顺序与setTimeouts本身相同,但依赖此行为是否安全?

Stj*_*jko 14

依赖这种行为是不安全的.我编写了一个测试脚本,它使用setTimeout(...,0)来调度许多函数(并且它们又调度了许多函数),并且调用函数的顺序并不总是与调用setTimeout的顺序(至少在我用来运行脚本的Chrome 11中).

您可以在此处查看/运行脚本:http://jsfiddle.net/se9Jn/ (该脚本使用YUI进行跨浏览器兼容,但Y.later在内部使用setTimeout).

请注意,如果您只是运行脚本并盯着控制台,则可能看不到违规排序.但是,如果启动脚本,切换到另一个选项卡,加载一些页面,然后返回测试页面,您应该会在控制台中看到有关回调的错误.

如果您需要保证订购,我建议在上一个函数结束时安排下一个函数:

setTimeout(foo, 0);

...

function foo() {

    ...

    setTimeout(bar, 0);
}
Run Code Online (Sandbox Code Playgroud)


jkl*_*jkl 13

我通读了Firefox源代码,至少对于那个浏览器,有一个顺序保证超时,以非递减顺序指定.否则所有投注都会被取消.

具体来说,如果在给定的执行上下文中为n设置了超时,然后为m设置了一个超时,其中n <= m,则将按设置超时的顺序执行目标.

但是不要相信我的话.我相信窗口实现在nsGlobalWindow.cpp中,实际决定超时在执行队列中的位置的方法称为InsertTimeoutIntoList.看起来该方法向后遍历队列,查找小于或等于给定超时的第一个超时,并在其后插入给定的超时.

当然,当设置超时时,当前时钟时间被添加到超时值.这就是为什么超时值必须按非递减顺序才能按顺序执行目标.


Jam*_*mes 5

答案是:不,不保证执行顺序。我偶尔会在 chrome 40 中看到非 FIFO 排序,特别是如果我在超时挂起时在调试器中暂停。我在野外也有一次罕见的目击 - 这是我调查的事件的唯一合理解释。

如果您需要保证执行顺序,setTimeout(callback, 0)您可以这样做:

var queue = [];
function handleQueue() {
    queue.shift()();
}
function queueCallback(callback) {
   queue.push(callback);
   setTimeout(handleQueue, 0);
}
Run Code Online (Sandbox Code Playgroud)

现在,为了保证foobar订购您可以:

queueCallback(foo);
...
queueCallback(bar);
Run Code Online (Sandbox Code Playgroud)


jld*_*ont 3

简而言之,不要指望它。看看这个

该图中有很多信息需要消化,但完全理解它将使您更好地了解异步 JavaScript 执行的工作原理。

  • 我在那篇文章中没有看到任何严格意义上的内容。问题不在于目标函数何时执行,而在于它们的执行顺序。 (7认同)
  • 当然,实际的延迟可能比预期的要长,并且间隔的工作方式与计时器不同,但本文并没有直接解决这个问题。不管执行“foo”需要0毫秒还是100年,它总是会发生在“bar”之前吗?还是浏览器可以任意选择?我觉得这方面必须有一个标准(或至少有一些信息)。 (4认同)