核心对象

主要关注

cwd
argv
env
execArgv

process.nextTick(callback[, …args]);

事件循环机制

宏任务

主线程中按序执行 task跟着task

  • 回调函数
  • XHR回调
  • setTimeout
  • setIntval
  • UI rending
  • IO
  • setImmidate

    • Node独有

      微任务

      task完成之后,插入进来
  • promise

  • process.nextTick
    • Node独有

node事件循环

借助libuv
Node.js 事件循环,定时器和 process.nextTick()
一个 tick 就是一个事件循环(6步)

  1. ┌───────────────────────────┐
  2. ┌─>│ timers
  3. └─────────────┬─────────────┘
  4. ┌─────────────┴─────────────┐
  5. pending callbacks
  6. └─────────────┬─────────────┘
  7. ┌─────────────┴─────────────┐
  8. idle, prepare
  9. └─────────────┬─────────────┘ ┌───────────────┐
  10. ┌─────────────┴─────────────┐ incoming:
  11. poll │<─────┤ connections,
  12. └─────────────┬─────────────┘ data, etc.
  13. ┌─────────────┴─────────────┐ └───────────────┘
  14. check
  15. └─────────────┬─────────────┘
  16. ┌─────────────┴─────────────┐
  17. └──┤ close callbacks
  18. └───────────────────────────┘

process.nextTick这个名字是有歧义(历史原因)的,实际是插在本轮的tick。

  1. setTimeout(()=>console.log(1));
  2. setImmediate(()=>console.log(2));
  3. process.nextTick(()=>console.log(3));
  4. Promise.resolve().then(()=>console.log(4));
  5. (()=>console.log(5))(); // 本轮的同步tick
  6. // 5 3 4 1 2
  7. // 5 3 4 2 1
  8. // setTimout 与 setImmediate 是不确定

如果单独运行setTimeout 和 setImmediate,结果可能不一致
image.png
原因是 setTimeout是存在一个时间间隔,在浏览器中是10ms以上,而node是更快人。但这个时间有可能为1ms或更快。
但如果是在一个异步回调中,如fs.readFile,这个结果就是一定的。timer要在下一个tick时才执行,即只会出现2 1。

在浏览器中
process 进程 - 图2
timer1 promise1 timer2 promise2

在node中
setTImout没有给延迟值时,此结果就不一致, 出现竞争态的问题
可能是timer1 promise1 timer2 promise2

timer1竞争赢timer2

或者 timer1 timer2 promise1 promise2

timer1竞争输了,在下一个tick再promise1 promise2