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

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

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

查看所有标签

猜你喜欢:

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

数据科学入门

数据科学入门

[美] Joel Grus / 高蓉、韩波 / 人民邮电出版社 / 2016-3 / 69.00元

数据科学是一个蓬勃发展、前途无限的行业,有人将数据科学家称为“21世纪头号性感职业”。本书从零开始讲解数据科学工作,教授数据科学工作所必需的黑客技能,并带领读者熟悉数据科学的核心知识——数学和统计学。 作者选择了功能强大、简单易学的Python语言环境,亲手搭建工具和实现算法,并精心挑选了注释良好、简洁易读的实现范例。书中涵盖的所有代码和数据都可以在GitHub上下载。 通过阅读本书,......一起来看看 《数据科学入门》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具