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.看起来该方法向后遍历队列,查找小于或等于给定超时的第一个超时,并在其后插入给定的超时.
当然,当设置超时时,当前时钟时间被添加到超时值.这就是为什么超时值必须按非递减顺序才能按顺序执行目标.
答案是:不,不保证执行顺序。我偶尔会在 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)
现在,为了保证foo,bar订购您可以:
queueCallback(foo);
...
queueCallback(bar);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2945 次 |
| 最近记录: |