事件循环简单梳理(浏览器&Nodejs)

2018-12-31  本文已影响29人  一个笑点低的妹纸
目录

一、介绍

在了解事件循环之前,首先需要了解两个概念:

(1)调用栈和任务队列

调用栈和任务队列关系图

主线程运行的时候,产生堆(heap)和栈(stack),栈中的代码调用各种外部API,它们在"任务队列"中加入各种事件(click,load,done)。只要栈中的代码执行完毕,主线程就会去读取"任务队列",依次执行那些事件所对应的回调函数。—— JavaScript 运行机制详解:再谈Event Loop,阮一峰

(2)宏任务和微任务是什么?划分的依据是什么?

宏任务(Task/macrotask) 是严格按照时间顺序压栈和执行的,所以浏览器能够使得 JavaScript 内部任务与 DOM 任务能够有序的执行。当一个 task 执行结束后,在下一个 task 执行开始前,浏览器可以对页面进行重新渲染。

微任务(Microtask) 通常来说就是需要在当前 task 执行结束后立即执行的任务,例如需要对一系列的任务做出回应,或者是需要异步的执行任务而又不需要分配一个新的 task,这样便可以减小一点性能的开销。

Task:script(全局任务),事件回调,XHR回调,setTimeout,setInterval,setImmediate(node独有),I/O,UI rendering
Microtask:更新应用程序状态的任务,包括Promise回调,MutationObserver,process.nextTick(node独有),Object.observe(废弃)

【注意】:

new Promise((resolve, reject) => {
    console.log('同步'); 
    resolve()}
).then(() => {
    console.log('异步');
})

Finally,什么是事件循环?

主线程从“任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为 Event Loop(事件循环)。

二、事件循环(浏览器)

事件处理过程 macrotask&microtask的执行顺序

浏览器环境下,microtask 的任务队列是每个 macrotask 执行完之后执行。

三、事件循环(Node.js)

JavaScript引擎作为将JavaScript解释为机器码的工具,分别运行在浏览器和Node中。而根据上下文的不同,Event loop也有不同的实现。

Node.js体系架构

在浏览器中,html规范定义了Event loop,具体的实现则交给不同的厂商去完成,而Node采用V8 作为js的解析引擎,在I/O处理方面使用了自己设计的libuv,libuv是一个基于事件驱动的跨平台抽象层,封装了不同操作系统一些底层特性,对外提供统一的API,事件循环机制也是它里面实现的。

Node.js事件处理

根据 Node.js 官方介绍,每次事件循环都包含了6个阶段,对应到 libuv 源码中的实现。
事件循环会无限次地执行,一轮又一轮。只有异步任务的回调函数队列清空了,才会停止执行。

Event Loop的执行顺序

在Node.js中,microtask 会在事件循环的各个阶段之间执行,也就是一个阶段执行完毕,就会去执行 microtask 队列的任务。
process.nextTick() 并没有在 Event Loop 的执行阶段中,而是在 Event Loop 两个阶段之间运行,根据上面说的,process.nextTick() 属于 microtask 任务类型。也就是 process.nextTick() 有可能插入在 Event Loop各个阶段中。

关于Node定时器(process.nextTick、setTimeout、setImmediate)方面的内容,请参阅 Node 定时器详解,阮一峰

四、参考

上一篇下一篇

猜你喜欢

热点阅读