check 阶段的 setImmediate 在 poll 阶段的 readFile 之前执行

来源:7-3 从 libuv 源码来理解 Event Loop 的 6 个阶段

ShineTech

2018-02-09

我的是 mac 环境 node 8.9.3, 代码与老师一致,但是打印的执行顺序中,属于第三阶段check的setImmediate 在 属于 第二阶段IO操作的readFile 之前执行。。。这就让我很困惑了。

const { readFile } = require('fs');
const EventEmitter = require('events');

const eve = new EventEmitter();

eve.on('hi', () => {
  console.log('hi')
})

setTimeout(() => {
  console.log('exec the 1st setTimeout timer')
}, 0)

setTimeout(() => {
  console.log('exec the 2nd setTimeout timer')
}, 50)

setTimeout(() => {
  console.log('exec the 3rd setTimeout timer')
}, 100)

readFile('./package.json', 'utf-8', data => {
  console.log('exec the 1st read file')
})

readFile('./package.json', 'utf-8', data => {
  console.log('exec the 2nd read file')
})

setImmediate(() => {
  console.log('exec the 1st setImmediate')
})

Promise.resolve().then(() => {
    process.nextTick(() => {
      console.log('exec the 2nd nextTick')
    })
    eve.emit('hi')
    console.log('exec the 1st promise')
  })
  .then(() => {
    console.log('exec the 2nd promise')
  })

process.nextTick(() => {
  console.log('exec the 1st nextTick')
})

http://img.mukewang.com/szimg/5a7e32f80001c98d05900482.jpg

写回答

2回答

Scott

2018-02-12

这个结果不一样的原因,在于 readfile 这里的处理,readfile 也就是 IO 是不稳定的,执行时间不等,导致它如果没 ready,那么timer 后就会进入到 check 执行 setImmediate,就是你这种结果,如果 IO ready,那么就是视频中的效果,这就是 Nodejs 里面 IO 魔性的地方,你可以把这个文件放到 /test 目录下,然后把 ./package.json 路径改成 ../package.json,多执行几次,会发现结果并不总是一致的,原因就在于 eventloop 转起来的时候,readfile 是否 ready,timer 是否到期进栈,这两个不确定因素会导致 setImmediate 会不会紧挨着 setTimeout 执行

1
2
ShineTech
这也解释了我的截屏中,第二个读操作为什么在第一个读操作之前执行了。。。Thhhhhhhx
2018-02-12
共2条回复

慕粉3563954

2019-07-30

找到答案了

0
0

Koa2框架从0开始构建预告片网站

Koa2+MongoDB+Parcel+Puppeteer+AntDesign快速搭建预告片网站

751 学习 · 362 问题

查看课程