JavaScript 事件循环中的微任务和宏任务是什么?
事件循环: JavaScript 中的事件循环被称为是一个不断运行的进程,它在调用堆栈上保留一个选项卡。它的主要函数是检查调用堆栈是否为空。如果调用堆栈为空,则事件循环继续执行任务队列中等待的所有回调。在任务队列中,任务大致分为两类,即微任务和宏任务。
事件循环中的微任务:微任务被称为是在创建它的函数或程序退出并且仅当 JavaScript 执行堆栈为空但在将控制权返回给正在使用的事件循环之前执行的函数由用户代理驱动脚本的执行环境。微任务还能够将其他微任务排队。
微任务通常安排在当前脚本执行后需要立即完成的事情上。完成一项宏任务后,事件循环将移至微任务队列。直到微任务队列内的所有任务都完成后,事件循环才会移动到微任务队列外的下一个任务。这意味着微任务队列具有更高的优先级。
一旦微任务队列中的所有任务都完成了,事件循环才会转移回宏任务队列。优先考虑微任务队列的主要原因是为了改善用户体验。鉴于任何其他 JavaScript 不在中间执行状态,微任务队列在回调之后处理。微任务包括变异观察者回调和承诺回调。
在新的微任务被添加到队列的这种情况下,这些额外的微任务被添加到微队列的末尾并且这些也被处理。这是因为事件循环将继续调用微任务,直到队列中没有更多微任务,即使不断添加新任务也是如此。使用微任务的另一个重要原因是确保任务的顺序一致,同时降低用户造成延迟的风险。
语法:添加微任务:
queueMicrotask(() => {
// Code to be run inside the micro-task
});
微任务函数本身不带参数,也不返回值。
示例: process.nextTick、Promises、queueMicrotask、MutationObserver
事件循环中的宏任务:宏任务代表一些离散和独立的工作。这些总是执行 JavaScript 代码并且微任务队列是空的。宏任务队列通常被认为与任务队列或事件队列相同。但是,宏任务队列的工作方式与任务队列相同。两者之间唯一的小区别是任务队列用于同步语句,而宏任务队列用于异步语句。
在 JavaScript 中,在事件发生之前不允许执行任何代码。 {值得一提的是,JavaScript 代码执行本身就是一个宏任务。} 事件作为宏任务排队。当正在执行存在于宏任务队列中的(宏)任务时,可以注册新事件并依次创建并添加到队列中。
在初始化时,JavaScript 引擎首先拉出宏任务队列中的第一个任务并执行回调处理程序。然后 JavaScript 引擎将这些异步函数发送到 API 模块,模块在适当的时候将它们推送到宏任务队列。一旦进入宏任务队列,每个宏任务都需要等待下一轮事件循环。这样,代码就被执行了。
记录的所有微任务都在单个宏任务执行周期中一举处理。相比之下,宏任务队列的优先级较低。宏任务包括解析 HTML、生成 DOM、执行主线程 JavaScript 代码和其他事件,例如页面加载、输入、网络事件、定时器事件等。
示例: setTimeout、setInterval、setImmediate、requestAnimationFrame、I/O、UI 渲染