【Promise 源码学习】第十八篇 - EventLoop 简介
一,前言
上一篇,主要介绍了 async/await 的使用和实现原理,主要涉及以下几个点:
async/await 的使用和功能分析;
async/await 的实现和原理分析;
本篇,继续介绍浏览器的事件环 EventLoop;
二,EventLoop 简介
EventLoop 是一个执行模型,在浏览器和 Node 中均有不同的实现:
在 Node 中,使用 libuv 库实现 EventLoop;
在浏览器中,由 Html 规范定义了 EventLoop;
在 JavaScript 代码执行的过程中,可能会进行发送请求、开启定时器等异步操作;
EventLoop 事件循环主要就负责完成相关任务的调度工作;比如:面试中经常问到的执行顺序问题;
备注:EventLoop 是前端领域的重要知识点,也是前端面试的核心考察点;
三,宏任务和微任务
在浏览器的事件循环 EventLoop 执行模型中,涉及宏任务和微任务;
常见宏任务:
JS 执行栈:js 在执行时就是一个宏任务;
定时器:setTimeout、setInterval;
postMessage、MessageChannel;
IE 下的 setImmediate 方法;
UI 的界面渲染;
事件;
Ajax;
常见微任务:
promise.then;
mutationObserver;
备注:为了方便记忆,可以简单理解为:除以上两种微任务之外,其余均为宏任务;
四,EventLoop 循环机制
浏览器 EventLoop 图示:
重要组成部分:
左边 - JS 执行线程:用于执行 JS;(JS 代码为栈型结构执行)
右边 - GUI 线程:用于界面的渲染;
上边 - 宏任务队列:用于存储运行中产生的宏任务;宏任务队列全局只有一个;
下边 - 微任务队列:用于存储运行中产生的微任务;宏任务队列每次循环产生一个;
备注:EventLoop 事件触发线程负责不停地轮训事件队列,并逐个取出进行处理;
代码的执行过程
代码执行
JS 代码从上到下执行,当执行到函数时,会创建执行上下文放入 JS 执行栈;
JS 代码中将包含同步代码和异步代码两种;
异步操作-宏任务(浏览器 API)
执行过程中,可能发生异步操作(如:定时器、ajax、事件等);
当异步操作的时间到达或成功时,将会被放入到事件队列中;(在事件队列中维护宏任务)
备注:由于队列具有先进先出的特点,因此可以保证代码的执行顺序;
事件循环线程
事件循环线程,用于不停地轮训扫描事件队列;事件循环线程,将对当前执行栈进行检测:若执行栈为空,将会从件队列中取出一个放入执行
备注:事件循环线程是一个单独的线程,所以并不会阻塞 JS 的执行;
异步操作-微任务( promise )
代码在执行时,还可能产生一些微任务,如 promise;
在微任务中产生的微任务会被放入当前宏任务下的微任务队列中,即会在当前轮次被情况;
备注:每次执行宏任务时,都会单独创建一个微任务队列;
GUI 渲染
浏览器渲染的频率是 16.6 ms,所以并不是每次微任务执行完成后都会执行渲染操作;
总结:每次循环一次,都会执行一个宏任务,并清空对应的微任务队列;
五,结尾
本篇,主要介绍了 EventLoop 的执行原理,主要涉及以下几个点:
EventLoop 简介;
宏任务和微任务;
EventLoop 循环机制
下一篇,待定;
评论