Javascript 在IE8中使用setTimeout防止长时间运行的脚本错误-为什么它依赖于时间间隔?

Javascript 在IE8中使用setTimeout防止长时间运行的脚本错误-为什么它依赖于时间间隔?,javascript,performance,internet-explorer-8,settimeout,Javascript,Performance,Internet Explorer 8,Settimeout,我正在尝试编写一些JavaScript来运行IE8。这与排序一个中等规模的数据集有关(实际上,对于99%的用户来说,这是一个非常小的数据集——但总是有一些边缘情况)。我一直在研究在IE8上执行长脚本的方法,既不阻塞UI也不导致“long Running script”消息 一种流行的解决方案是使用window.setTimeout交错函数调用,然后在末尾异步返回该变量。常见的建议是编写递归函数并使用 window.setTimeout(fn, 1); 因为这应该将调用添加到线程的事件队列中。U

我正在尝试编写一些JavaScript来运行IE8。这与排序一个中等规模的数据集有关(实际上,对于99%的用户来说,这是一个非常小的数据集——但总是有一些边缘情况)。我一直在研究在IE8上执行长脚本的方法,既不阻塞UI也不导致“long Running script”消息

一种流行的解决方案是使用window.setTimeout交错函数调用,然后在末尾异步返回该变量。常见的建议是编写递归函数并使用

window.setTimeout(fn, 1);
因为这应该将调用添加到线程的事件队列中。UI操作将与setTimeout调用交错,浏览器将保持响应。IE8不会抱怨,因为它的语句计数器在调用超时时被重置

但我有个问题我发现在IE8中,长时间运行的脚本异常只有在超时足够长时才会消失

我编写了一些函数,使用交错函数调用将数字增加到300万,每个函数调用执行50000个n++操作。这些函数执行许多操作(实际上,甚至比我最糟糕的用例还要多),但没有一个函数会破坏IE的记录。但问题是:如果我将函数错开1ms的超时时间,我会在IE8中得到一个长时间运行的脚本警告(在多次函数调用之后)。如果我错开15毫秒的超时时间,我不会。为什么?这与Win32计时API的粒度有关吗

这是一个JSFIDLE:,以及一个您可以在IE8中自己尝试的嵌入式版本 :


编辑:奇怪的是,如果我使用600000次迭代计算到900万次,我可以用15ms代码复制相同的问题。这也会提示IE8中的“停止运行此脚本”对话框。因此,这似乎与操作量和超时长度有关。

不要被欺骗,以为
setTimeout
会产生一个新线程,因为它不会。它只需将回调函数调用推到调用队列的末尾,并在主线程中(大约)Xms delay之后调用该函数。使用1ms的超时可能意味着您的队列中充满了对
fn
的连续调用,这导致IEcomplain@EliasVanOotegem-当然,如果我没有通过点击或触发任何其他UI事件来中断计数,那么15ms代码将显示相同的行为?就我所知,它不是。不一定:如果IE8从调用
setTimeout
的点开始需要超过1ms,那么调用堆栈将包含对函数的2个调用,可能会达到指令限制并阻塞调用堆栈,从而有效地阻塞UI(事件循环等)。15毫秒的延迟可能足以让JScript引擎空转几毫秒,让IE检查事件循环,并正常进行。我只是在这里猜测(我的任何机器上都没有IE,所以无法检查)。可能你最好做一些挖掘,有一些具体的方法可以帮助你这样做。希望有一个工具可以告诉您实际代码在内部翻译了多少指令。结果通常可能考虑使用闭包,并在需要的时候绑定和解除绑定事件处理程序。这将使您能够保持事件循环轻。(输出使用
console.log
,因此使用控制台检查其功能)