事件循环,是 js 中老生常谈的一个话题了,而在浏览器和 Node 中的事件循环执行机制也不相同,浏览器的事件循环是在 HTML5 中定义的规范,而 Node 中则是由 libuv 库实现。
浏览器中的事件循环:
1. Micro-Task 与 Macro-Task
事件循环中的异步队列有两种:macro(宏任务)队列和 micro(微任务)队列。宏任务队列可以有多个,微任务队列只有一个。
-
常见的 macro-task 比如:setTimeout、setInterval、 setImmediate、script(整体代码)、 I/O 操作、UI 渲染等。
-
常见的 micro-task 比如: process.nextTick、new Promise().then(回调)、MutationObserver(html5 新特性) 等。
2.事件循环过程解析
一个完整的 Event Loop 过程,可以概括为以下阶段:
1、一开始执行栈空,我们可以把执行栈认为是一个存储函数调用的栈结构,遵循先进后出的原则。micro 队列空,macro 队列里有且只有一个 script 脚本(整体代码)。
2、全局上下文(script 标签)被推入执行栈,同步代码执行。在执行的过程中,会判断是同步任务还是异步任务,通过对一些接口的调用,可以产生新的 macro-task 与 micro-task,它们会分别被推入各自的任务队列里。
同步代码执行完了,script 脚本会被移出 macro 队列,这个过程本质上是队列的 macro-task 的执行和出队的过程。
3、上一步我们出队的是一个 macro-task,这一步我们处理的是 micro-task。但需要注意的是:当 macro-task 出队时,任务是一个一个执行的;而 micro-task 出队时,任务是一队一队执行的。
因此,我们处理 micro 队列这一步,会逐个执行队列中的任务并把它出队,直到队列被清空。
4、执行渲染操作,更新界面
5、检查是否存在 Web worker 任务,如果有,则对其进行处理
6、上述过程循环往复,直到两个队列都清空
Node 中的事件循环
Node 中的 Event Loop 和浏览器中的是完全不相同的东西。Node.js 采用 V8 作为 js 的解析引擎,而 I/O 处理方面使用了自己设计的 libuv。
libuv 是一个基于事件驱动的跨平台抽象层,封装了不同操作系统一些底层特性,对外提供统一的 API,事件循环机制也是它里面的实现。
Node.js 的运行机制如下:
-
V8 引擎解析 JavaScript 脚本。
-
解析后的代码,调用 Node API。
-
libuv 库负责 Node API 的执行。它将不同的任务分配给不同的线程,形成一个 Event Loop(事件循环),以异步的方式将任务的执行结果返回给 V8 引擎。
-
V8 引擎再将结果返回给用户。
Node与浏览器事件循环的差异
浏览器环境下,microtask 的任务队列是每个 macrotask 执行完之后执行。而在 Node.js 中,microtask 会在事件循环的各个阶段之间执行,也就是一个阶段执行完毕,就会去执行 microtask 队列的任务。
总结
浏览器和 Node 环境下,microtask 任务队列的执行时机不同
-
Node 端,microtask 在事件循环的各个阶段之间执行
-
浏览器端,microtask 在事件循环的 macrotask 执行完之后执行
以上就是node事件循环和浏览器事件循环来源gaodai$ma#com搞$代*码网的区别是什么?的详细内容,更多请关注gaodaima搞代码网其它相关文章!