【7-4】事件循环中第二阶段异步IO和第三阶段check的执行顺序的问题

来源:7-4 设计一个测试用例来验证自己对事件循环的理解

慕名小白

2018-04-03

//img.mukewang.com/szimg/5ac3503000019a2411161056.jpg

scott好,

const { readFile, readFileSync } = require('fs')


setImmediate(() =>  console.log('[阶段3.immediate] immediate 回调1'))
setImmediate(() =>  console.log('[阶段3.immediate] immediate 回调2'))
setImmediate(() =>  console.log('[阶段3.immediate] immediate 回调3'))

Promise.resolve()
  .then(() => {
    console.log('[...等待切入下一个阶段] promise 回调 1')
    setImmediate(() => console.log('[阶段3.immediate] promise 回调1 增加的 immediate 回调4'))
  })

readFile('../package.json', 'utf-8', data => {
  console.log('[阶段2...IO 回调] 读文件回调1')

  readFile('../package-lock.json', 'utf-8', data => {
    console.log('[阶段2...IO 回调] 读文件回调2')
    setImmediate(() => console.log('[阶段3.immediate] 读文件回调2 增加的 immediate 回调4'))
  })

  setImmediate(() =>  {
    console.log('[阶段3.immediate] immediate 回调5')

    Promise.resolve()
      .then(() => {
        console.log('[...等待切入下一个阶段] promise 回调 2')

        process.nextTick(() => {
          console.log('[...待切入下一个阶段] promise 回调2增加的 nextTick 回调5')
        })
      })
      .then(() => {
        console.log('[...等待切入下一个阶段] promise 回调 3')
      })
  })

  setImmediate(() =>  {
    console.log('[阶段3.immediate] immediate 回调6')

    process.nextTick(() => {
      console.log('[...待切入下一个阶段] immediate 回调6 nextTick 回调7')
    })
    console.log('[...待切入下一个阶段] 这块正在同步阻塞的读一个大文件')
    const video = readFileSync('../package-lock.json', 'utf-8')
    process.nextTick(() => {
      console.log('[...待切入下一个阶段] immediate 回调6 nextTick 回调8')
    })

    readFile('../package.json', 'utf-8', data => {
      console.log('[阶段2...IO回调] 读文件回调3')

      setImmediate(() => console.log('[阶段3.immediate] 读文件回调3 增加的 immediate 回调6'))

      setTimeout(() => console.log('[阶段1...定时器] 读文件回调3 增加的 定时器回调8'), 0)
    })
  })

  process.nextTick(() => {
    console.log('[...待切入下一个阶段] 读文件 回调1 增加的 nextTick 回调6')
  })

  setTimeout(() => console.log('[阶段1...定时器] 定时器 回调5'), 0)
  setTimeout(() => console.log('[阶段1...定时器] 定时器 回调6 '), 0)
})

setTimeout(() => console.log('[阶段1...定时器] 定时器 回调1'), 0)
setTimeout(() => {
  console.log('[阶段1...定时器] 定时器 回调2')

  process.nextTick(() => {
    console.log('[...待切入下一个阶段] nextTick 回调5')
  })
}, 0)
setTimeout(() => console.log('[阶段1...定时器] 定时器 回调3'), 0)
setTimeout(() => console.log('[阶段1...定时器] 定时器 回调4'), 0)

process.nextTick(() => console.log('[...待切入下一个阶段] nextTick 回调1'))
process.nextTick(() => {
  console.log('[...待切入下一个阶段] nextTick 回调2')
  process.nextTick(() => console.log('[...待切入下一个阶段] nextTick 回调4'))
})
process.nextTick(() => console.log('[...待切入下一个阶段] nextTick 回调3'))

在执行timers阶段70行~79行中的这个打印的setTimout中有一个nextTick([...待切入下一个阶段] nextTick 回调5,执行完这个后

就该进入到第二阶段,但是为什么图中,我画框的打印中,第三阶段的immediate会比异步IO先执行呢?同样的,后面的一个框也是这样的问题,我没有想明白这是为什么?

写回答

2回答

Scott

2018-04-05

IO 是事件循环中,最不可控的一个环节了,它与 immediate 的关系,从你贴的图上看,也是成立的,immediate 是在 ready 阶段来执行,而 IO 是在之前,但这个之前只是逻辑上的之前,在 Next tick 执行完毕之后,immediate 往往会比 IO 这个先执行。


课程的这个示例是比较极端的形式,我建议你大概知道这阶段后,来看下更深入的一个时间循环探究,是好几篇文章来讲述:


https://www.zcfy.cc/article/event-loop-and-the-big-picture-nodejs-event-loop-part-1-3566.html?t=new



这是中文版,英文版的系列是 5 篇吧,更全,通过这个来理解这个执行结果,会更全面一些

0
0

慕名小白

提问者

2018-04-04

再来补充一下环境,node版本是v8.4.0,把node版本切换到v8.9.4执行结果还是一样的

0
0

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

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

751 学习 · 362 问题

查看课程