setImmediate() function is called after setTimeout() function
在nodejs的官方网站(https://nodejs.org/api/timers.html#timers_setimmediate_callback_arg)中,据说:
setImmediate() function schedules"immediate" execution of callback
after I/O events' callbacks and before timers set by setTimeout and
setInterval are triggered.
但是,在下面的代码中,setTimeout()函数在setImmediate()之前执行。 为什么?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | setImmediate(function A() { setImmediate(function B() { console.log(1); setImmediate(function D() { console.log(2); }); setImmediate(function E() { console.log(3); }); }); setImmediate(function C() { console.log(4); setImmediate(function F() { console.log(5); }); setImmediate(function G() { console.log(6); }); }); }); setTimeout(function timeout() { console.log('TIMEOUT FIRED'); }, 0) |
结果:
1 2 3 4 5 6 7 | TIMEOUT FIRED 1 4 2 3 5 6 |
我写了另一个示例,并且
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | setTimeout(function timeout() { console.log('TIMEOUT-1 FIRED'); }, 0) setTimeout(function timeout() { console.log('TIMEOUT-2 FIRED'); }, 0) setImmediate(function D() { console.log(1); }); setImmediate(function D() { console.log(2); }); setImmediate(function D() { console.log(3); }); setTimeout(function timeout() { console.log('TIMEOUT-1 FIRED'); }, 0) setTimeout(function timeout() { console.log('TIMEOUT-2 FIRED'); }, 0) |
输出:
1 2 3 4 5 6 7 | TIMEOUT-1 FIRED TIMEOUT-2 FIRED TIMEOUT-1 FIRED TIMEOUT-2 FIRED 1 2 3 |
让我们将上面的示例编写如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | var fs = require('fs') fs.readFile("readme.txt", function (){ setTimeout(function timeout() { console.log('TIMEOUT-1 FIRED'); }, 0) setTimeout(function timeout() { console.log('TIMEOUT-2 FIRED'); }, 0) setImmediate(function D() { console.log(1); }); setImmediate(function D() { console.log(2); }); setImmediate(function D() { console.log(3); }); setTimeout(function timeout() { console.log('TIMEOUT-1 FIRED'); }, 0) setTimeout(function timeout() { console.log('TIMEOUT-2 FIRED'); }, 0)}) |
输出:
1 2 3 4 5 6 7 | 1 2 3 TIMEOUT-1 FIRED TIMEOUT-2 FIRED TIMEOUT-1 FIRED TIMEOUT-2 FIRED |
说明:
计时器的执行顺序将根据调用它们的上下文而有所不同。如果两者都是从主模块中调用的,则时序将受到进程性能的限制(这可能会受到计算机上运行的其他应用程序的影响)。
例如,如果我们运行以下不在I / O周期(即主模块)内的脚本,则两个计时器的执行顺序是不确定的,因为它受进程性能的约束:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // timeout_vs_immediate.js setTimeout(function timeout () { console.log('timeout'); },0); setImmediate(function immediate () { console.log('immediate'); }); $ node timeout_vs_immediate.js timeout immediate $ node timeout_vs_immediate.js immediate timeout |
但是,如果您在一个I / O周期内移动这两个调用,则始终首先执行立即回调:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // timeout_vs_immediate.js var fs = require('fs') fs.readFile(__filename, () => { setTimeout(() => { console.log('timeout') }, 0) setImmediate(() => { console.log('immediate') }) }) $ node timeout_vs_immediate.js immediate timeout $ node timeout_vs_immediate.js immediate timeout |
与setTimeout()相比,使用setImmediate()的主要优点是,如果在I / O周期内安排了任何计时器,则setImmediate()将始终在任何计时器之前执行,而与存在多少计时器无关。
有关更多信息,请参考以下链接:
https://github.com/nodejs/node/blob/master/doc/topics/the-event-loop-timers-and-nexttick.md