node端事件循环机制(Part2 - Timers、 Immediates 、 Next Ticks)

栏目: JavaScript · 发布时间: 6年前

内容简介:欢迎回来,在第一篇文章中, 描述了NodeJS事件循环的总体情况,在这一节中,将通过代码实例详细讨论三种重要的队列。它们是,这带来了一个新问题。使用process递归/重复地向nextTick队列添加事件。nextTick函数可能导致I/O和其他队列永远饿死。我们可以使用下面的简单脚本模拟这个场景。

欢迎回来,在第一篇文章中, 描述了NodeJS事件循环的总体情况,在这一节中,将通过代码实例详细讨论三种重要的队列。它们是, timers , immediatesprocess.nextTick 的回掉.

node端事件循环机制(Part2 - Timers、 Immediates 、 Next Ticks)

文章指引

  • 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')
    })
});

接下来我们来看一下它的执行流程

  1. 在开始时,这个程序使用 fs.readFile 异步读取当前文件。它提供一个回调函数,在读取文件后触发。
  2. 然后事件循环开始。
  3. 一旦读取文件后,它将在事件循环的I/O队列中添加事件(要执行的回调)。
  4. 由于没有要处理的其他事件,Node正在等待任何I/O事件。然后,它将在I/O队列中看到文件读取事件并执行它。
  5. 在回调的执行过程中, timer 被添加到 timer 堆中,并且 Immediates 被添加到 Immediates 队列中
  6. 现在我们知道事件循环处于I/O阶段。由于没有要处理的任何I/O事件,因此事件循环将移动到immediate阶段,然后立即执行 immediate 回调。
  7. 在事件循环的下一个循环中,它将看到过期的 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'));
  1. 首先会有如下的一些事件被添加到事件队列中

    • 3 immediates
    • 5 timer 回掉
    • 5 next tick 回掉
  2. 当事件循环开始时,它将注意到 next tick 队列并开始处理 next tick 的回调。在执行第二个 next tick 回调期间,一个新的 next tick 回调被添加到 next tick 队列的末尾,并将在 next tick 队列的末尾执行。
  3. 将执行过期 timer 的回调。在第二个 timer 回调函数的执行过程中,一个事件被添加到 next tick 队列中。
  4. 一旦执行了所有过期 timer 的回调,事件循环将看到下一个 timer 队列中有一个事件(这是在执行第二个 timer 回调期间添加的)。然后事件循环将执行它。
  5. 由于没有要处理的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)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

互联网思想十讲

互联网思想十讲

段永朝 / 商务印书馆 / 2014-10 / 68.00

本书是作者为北京大学新闻与传播学院硕士生开设的《互联网前沿思想》课程的讲义。作者力图从技术、经济和社会的角度,在大尺度上观察互联网究竟根植于什么样的文化土壤。作者选择了复杂性、社会网络分析、公共空间这三个维度展开分析,为读者呈现出了脱胎于工业时代的互联网继承了哪些思想,并对哪些思想做出了彻底的颠覆。一起来看看 《互联网思想十讲》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

在线进制转换器
在线进制转换器

各进制数互转换器

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具