前言#
Event Loop 即事件循环,是指浏览器或 Node 的一种解决 javaScript 单线程运行时不会阻塞的一种机制,也就是我们经常使用异步的原理。
Event Loop#
在 JavaScript 中,任务被分为两种,一种宏任务(MacroTask)也叫 Task,一种叫微任务(MicroTask)。
MacroTask(宏任务)#
script 全部代码、setTimeout、setInterval、setImmediate(浏览器暂时不支持,只有 IE10 支持,具体可见 MDN)、I/O、UI Rendering。
MicroTask(微任务)#
Process.nextTick(Node 独有)、Promise、Object.observe (废弃)、MutationObserver(具体使用方式查看这里)
浏览器中的 Event Loop#
Javascript 有一个 main thread 主线程和 call-stack 调用栈 (执行栈),所有的任务都会被放到调用栈等待主线程执行。
JS 调用栈#
JS 调用栈采用的是后进先出的规则,当函数执行的时候,会被添加到栈的顶部,当执行栈执行完成后,就会从栈顶移出,直到栈内被清空。
同步任务和异步任务#
Javascript 单线程任务被分为同步任务和异步任务,同步任务会在调用栈中按照顺序等待主线程依次执行,异步任务会在异步任务有了结果后,将注册的回调函数放入任务队列中等待主线程空闲的时候(调用栈被清空),被读取到栈内等待主线程的执行。
任务队列 Task Queue,即队列,是一种先进先出的一种数据结构。
事件循环的进程模型#
选择当前要执行的任务队列,选择任务队列中最先进入的任务,如果任务队列为空即 null,则执行跳转到微任务(MicroTask)的执行步骤。
将事件循环中的任务设置为已选择任务。
执行任务。
将事件循环中当前运行任务设置为 null。
将已经运行完成的任务从任务队列中删除。
microtasks 步骤:进入 microtask 检查点。
更新界面渲染。
返回第一步。
执行进入 microtask 检查点时,用户代理会执行以下步骤:#
设置 microtask 检查点标志为 true。
当事件循环 microtask 执行不为空时:选择一个最先进入的 microtask 队列的 microtask,将事件循环的 microtask 设置为已选择的 microtask,运行 microtask,将已经执行完成的 microtask 为 null,移出 microtask 中的 microtask。
清理 IndexDB 事务
设置进入 microtask 检查点的标志为 false。