4

这与如何setTimeout执行其回调有关。

我有以下

function f1 (argument) {
    console.log('f1 start');
    for(var i = 0; i < 100000; ++i)
        for(var j = 0; j < 10000; ++j);
    console.log('f1 complete');
}

function f2 (argument) {
    console.log('f2 start');
    for(var i = 0; i < 1000; ++i)
        for(var j = 0; j < 10000; ++j);
    console.log('f2 complete');
}

function f3 (argument) {
    console.log('f3 start');
    for(var i = 0; i < 10000; ++i)
        for(var j = 0; j < 10000; ++j);
    console.log('f3 complete');
}

setTimeout(f1,0);
setTimeout(f2,0);
setTimeout(f3,0);
console.log('In main2');

输出:

在 main2

f1 开始

f1 完成

f3 开始

f3 完成

f2 开始

f2 完成

John Resig 在他的文章中解释说,将setTimeout所有回调排队,直到当前代码块完成其执行。这个 StackOverflow答案解释了即使看起来好像事件是立即触发的,但它们实际上是排队的。

在上面的代码中,您会注意到,f1()是最长的,其次是 f 3(),然后是f2()

我的问题是,为什么观察到的顺序(f1首先,然后f3,最后f2)?如果事件被排队,它应该与它们被调用的顺序相同(f1, f2, f3)。JavaScript 引擎如何以及为什么首先选择最长的工作?

[编辑] 注意:上面的代码是在 Node.js 中运行的

4

2 回答 2

1

我已经在 firebug 控制台中尝试了您的代码,并且按以下顺序得到了输出,我认为这符合预期。

在 main2 f1 开始 f1 完成 f2 开始 f2 完成 f3 开始 f3 完成

我正在使用 Firefox 12.0 和 Fedora。

于 2013-09-20T07:59:42.023 回答
0

不管“javascript引擎”问题(没有这样的东西,有语言规范和不同的实现),因为它取决于(参见this another answer),如果您想确保特定的序列顺序,您可能需要使用promises。

在https://github.com/kriskowal/q检查 Q 库

或者这个 RSVP 库https://github.com/tildeio/rsvp.js

Promises/a+ 规范在这里

可用于节点和浏览器

我自己在节点 v0.10.21 上的测试(与 firefox 和 chromium 的控制台相同):

~/workspace/tmp$ node test.js 
In main2
f1 start
f1 complete
f2 start
f2 complete
f3 start
f3 complete
于 2013-12-28T22:00:36.860 回答