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

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

内容简介:欢迎回来,在第一篇文章中, 描述了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)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

认知与设计

认知与设计

Jeff Johnson / 张一宁、王军锋 / 人民邮电出版社 / 2014-8-1 / CNY 69.00

本书语言清晰明了,将设计准则与其核心的认知学和感知科学高度统一起来,使得设计准则更容易地在具体环境中得到应用。涵盖了交互计算机系统设计的方方面面,为交互系统设计提供了支持工程方法。不仅如此,这也是一本人类行为原理的入门书。一起来看看 《认知与设计》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具