事件循环机制
推荐相关阅读文章
- 阮一峰老师的JavaScript 运行机制详解:再谈Event Loop
- 什么是js的事件循环 —— youtube视频有中文字幕,需要翻墙,非常值得一看 * 作者Philip Roberts
- js事件循环 —— 英文视频翻墙 * 作者Philip Roberts
- js异步运行机制(宏任务与微任务) —— 英文版
- js异步运行机制(宏任务与微任务) —— 翻译
一次完整的事件循环的过程大致可以概括为以下步骤
- 初始状态下,js调用栈为空,微任务(micro)为空,宏任务(macro)中只有一个script脚本(整个js代码)。
- 开始运行脚本,宏任务推入调用栈,开始执行代码。在执行代码的过程中会生成新的宏任务和微任务,他们会被推入各自的任务队列中。在脚本运行完毕后,script脚本会从宏任务队列中推出。
- 如果在执行宏任务的过程中产生微任务,此时会继续执行微任务,直到微任务执行完毕。
- 执行页面渲染,更新界面。
- 检测是否存在webworker任务,如果有,则对其进行运行。
示意图
示意图
自己划的重点
- 浏览器渲染界面的时机:浏览器会在一次宏任务结束后,下一次宏任务执行前进行页面的渲染。渲染页面的时候不会执行js。
- 在浏览器内,UI 渲染线程与 JavaScript 引擎线程为互斥的关系,当 JavaScript 引擎线程执行时 UI 渲染线程会被挂起,UI 更新会被保存在一个队列中等到 JavaScript 引擎线程空闲时立即被执行。
Event Loop(事件循环)
-
我们可以将整个部分分为三个部分,1、JS stack 2、Tasks(宏任务) 3、Microtasks(微任务)
-
请看下面代码
console.log('script start'); setTimeout(function() { console.log('setTimeout'); }, 0); Promise.resolve().then(function() { console.log('promise1'); }) console.log('script end');
当上述代码开始执行时,流程如下:
- Tasks内存有 script 脚本, script 脚本会被推入JS stack
- 开始执行 script 脚本,期间会产生输出 script start 和 script end ,setTimeout 会推入 Tasks 中,Promise.then 会推入 Microtasks 中。
- script 脚本执行结束后,会从 JS Stack 中推出,此时JS Stack栈内为空,Promise.then 将推入 JS stack 中,开始执行,输出 promise1 ,执行完毕后 Promise.then 从 Microtasks 中推出。
- 此时,浏览器开始更新界面。
- 浏览器更新完界面后,setTimeout 推入 JS Stack 栈,执行输出 setTimeout ,执行完毕后,setTimeout 从 Tasks 中推出。JS stack 内为空, Microtasks 为空。
- 此时,更新界面
简单来说:
-
主线程从”任务队列”中读取事件,这个过程是循环不断的。主线程运行的时候,产生堆(heap)和栈(stack),只要栈中的代码执行完毕,主线程就会去读取”任务队列”,依次执行那些事件所对应的回调函数。
-
JS 引擎对事件队列(宏任务)与JS引擎内的任务(微任务)执行存在着先后循序,当每执行完一个事件队列的时间,JS引擎会检测内部是否有未执行的任务,如果有,将会优先执行(微任务)。
网友评论