Skip to content

第 25 题:浏览器和Node 事件循环的区别

浏览器

关于微任务和宏任务在浏览器的执行顺序是这样的:

  • 执行一只 task(宏任务)
  • 执行完 micro-task 队列 (微任务)

如此循环往复下去

信息

浏览器的 task(宏任务)执行顺序在 html#event-loops 里面有讲就不翻译了

常见的 task(宏任务) 比如:setTimeoutsetIntervalscript(整体代码)、 I/O 操作、UI 渲染等。

常见的 micro-task 比如: new Promise().then(回调)MutationObserver(html5新特性) 等。

最新谷歌浏览器已经抛弃了宏任务的说法,具体请看我发的这篇文章:浏览器进程模型及事件循环机制

Node

Node 的事件循环是 libuv 实现的,引用一张官网的图:

大体的 task(宏任务)执行顺序是这样的:

  • timers 定时器:本阶段执行已经安排的 setTimeout()setInterval() 的回调函数。
  • pending callbacks 待定回调:执行延迟到下一个循环迭代的 I/O 回调。
  • idle, prepare:仅系统内部使用。
  • poll 轮询:检索新的 I/O 事件;执行与 I/O 相关的回调(几乎所有情况下,除了关闭的回调函数,它们由计时器和 setImmediate() 排定的之外),其余情况 node 将在此处阻塞。
  • check 检测:setImmediate() 回调函数在这里执行。
  • close callbacks 关闭的回调函数:一些准备关闭的回调函数,如:socket.on('close', ...)

微任务和宏任务在 Node 的执行顺序

Node 10 以前:

  • 执行完一个阶段的所有任务
  • 执行完 nextTick 队列里面的内容
  • 然后执行完微任务队列的内容

Node 11以后: 和浏览器的行为统一了,都是每执行一个宏任务就执行完微任务队列。