node端事件循环机制(Part2 - Timers、 Immediates 、 Next Ticks)
栏目: JavaScript · 发布时间: 5年前
内容简介:欢迎回来,在第一篇文章中, 描述了NodeJS事件循环的总体情况,在这一节中,将通过代码实例详细讨论三种重要的队列。它们是,这带来了一个新问题。使用process递归/重复地向nextTick队列添加事件。nextTick函数可能导致I/O和其他队列永远饿死。我们可以使用下面的简单脚本模拟这个场景。
欢迎回来,在第一篇文章中, 描述了NodeJS事件循环的总体情况,在这一节中,将通过代码实例详细讨论三种重要的队列。它们是, timers
, immediates
和 process.nextTick
的回掉.
文章指引
- Event Loop
- Timers、 Immediates 、 Next Ticks (本文)
- Promises、Next-Ticks、Immediates
- 处理 I/O
- 最佳的事件循环练习
- 在 Node v11中timers、microtasks发生的改变
I/O饥饿 例子一
这带来了一个新问题。使用process递归/重复地向nextTick队列添加事件。nextTick函数可能导致I/O和其他队列永远饿死。我们可以使用下面的简单脚本模拟这个场景。
const fs = require('fs'); function addNextTickRecurs(count) { let self = this; if (self.id === undefined) { self.id = 0; } if (self.id === count) return; process.nextTick(() => { console.log(`process.nextTick call ${++self.id}`); addNextTickRecurs.call(self, count); }); } addNextTickRecurs(Infinity); setTimeout(console.log.bind(console, 'omg! setTimeout was called'), 10); setImmediate(console.log.bind(console, 'omg! setImmediate also was called')); fs.readFile(__filename, () => { console.log('omg! file read complete callback was called!'); }); console.log('started');
您可以看到输出是一个无限循环的nextTick回调调用,以及 setTimeout、setImmediate 和fs.readFile
。从未调用readFile回调.
started process.nextTick call 1 process.nextTick call 2 process.nextTick call 3 process.nextTick call 4 process.nextTick call 5 process.nextTick call 6 process.nextTick call 7 process.nextTick call 8 process.nextTick call 9 process.nextTick call 10 process.nextTick call 11 process.nextTick call 12 ....
例二
const fs = require('fs'); fs.readFile(__filename, () => { setTimeout(() => { console.log('timeout') }, 0); setImmediate(() => { console.log('immediate') }) });
接下来我们来看一下它的执行流程
- 在开始时,这个程序使用
fs.readFile
异步读取当前文件。它提供一个回调函数,在读取文件后触发。 - 然后事件循环开始。
- 一旦读取文件后,它将在事件循环的I/O队列中添加事件(要执行的回调)。
- 由于没有要处理的其他事件,Node正在等待任何I/O事件。然后,它将在I/O队列中看到文件读取事件并执行它。
- 在回调的执行过程中, timer 被添加到 timer 堆中,并且 Immediates 被添加到 Immediates 队列中
- 现在我们知道事件循环处于I/O阶段。由于没有要处理的任何I/O事件,因此事件循环将移动到immediate阶段,然后立即执行 immediate 回调。
- 在事件循环的下一个循环中,它将看到过期的 timer 并执行 timer 回调。
例三
setImmediate(() => console.log('this is set immediate 1')); setImmediate(() => console.log('this is set immediate 2')); setImmediate(() => console.log('this is set immediate 3')); setTimeout(() => console.log('this is set timeout 1'), 0); setTimeout(() => { console.log('this is set timeout 2'); process.nextTick(() => console.log('this is process.nextTick added inside setTimeout')); }, 0); setTimeout(() => console.log('this is set timeout 3'), 0); setTimeout(() => console.log('this is set timeout 4'), 0); setTimeout(() => console.log('this is set timeout 5'), 0); process.nextTick(() => console.log('this is process.nextTick 1')); process.nextTick(() => { process.nextTick(console.log.bind(console, 'this is the inner next tick inside next tick')); }); process.nextTick(() => console.log('this is process.nextTick 2')); process.nextTick(() => console.log('this is process.nextTick 3')); process.nextTick(() => console.log('this is process.nextTick 4'));
-
首先会有如下的一些事件被添加到事件队列中
- 3 immediates
- 5 timer 回掉
- 5 next tick 回掉
- 当事件循环开始时,它将注意到 next tick 队列并开始处理 next tick 的回调。在执行第二个 next tick 回调期间,一个新的 next tick 回调被添加到 next tick 队列的末尾,并将在 next tick 队列的末尾执行。
- 将执行过期 timer 的回调。在第二个 timer 回调函数的执行过程中,一个事件被添加到 next tick 队列中。
- 一旦执行了所有过期 timer 的回调,事件循环将看到下一个 timer 队列中有一个事件(这是在执行第二个 timer 回调期间添加的)。然后事件循环将执行它。
- 由于没有要处理的I/O事件,因此事件循环将移动到即时队列并处理即时队列。
执行结果是下面这个样子
this is process.nextTick 1 this is process.nextTick 2 this is process.nextTick 3 this is process.nextTick 4 this is the inner next tick inside next tick this is set timeout 1 this is set timeout 2 this is set timeout 3 this is set timeout 4 this is set timeout 5 this is process.nextTick added inside setTimeout this is set immediate 1 this is set immediate 2 this is set immediate 3
Reference
以上所述就是小编给大家介绍的《node端事件循环机制(Part2 - Timers、 Immediates 、 Next Ticks)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- JS事件循环机制
- JavaScript运行机制和事件循环
- JS JavaScript事件循环机制
- 深入了解nodejs的事件循环机制
- js事件循环机制(event loop)
- 前端中的事件循环eventloop机制
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。