JavaScript 没有宏任务和微任务

在 JavaScript 中,宏任务和微任务的概念是建立在事件循环机制之上的一种抽象描述,用于帮助理解异步任务的执行顺序和优先级。实际上,JavaScript 中并没有宏任务和微任务这两个直接的概念,而是通过事件循环 (Event Loop) 来实现异步任务的调度和执行。

事件循环机制

JavaScript 是单线程语言,这意味着它一次只能执行一个任务。然而,为了处理用户的输入、网络请求等异步操作,JavaScript 引擎采用了事件循环机制来模拟并发执行。事件循环机制负责管理和调度异步任务的执行,它会不断地从事件队列中取出任务执行,直至所有任务执行完毕。

事件循环是一个不断循环的过程,它包含以下步骤:

  1. 检查是否有待处理的宏任务。
  2. 如果有,则执行该宏任务。
  3. 在宏任务执行期间,如果遇到微任务,则将微任务添加到微任务队列中。
  4. 宏任务执行完毕后,检查微任务队列,并执行队列中的所有微任务。
  5. 渲染页面。

宏任务与微任务的执行时机

宏任务 (Macrotask) 代表着一组任务,每个宏任务会在当前事件循环中执行完毕后执行。常见的宏任务包括定时器回调函数、DOM 事件处理函数、网络请求回调函数等。典型的宏任务包括:

  • setTimeout() 和 setInterval()
  • 脚本执行
  • DOM 事件处理程序
  • Ajax 请求

微任务 (Microtask) 则代表着一组需要尽快执行的任务,每个微任务会在当前宏任务执行完毕后立即执行。微任务的优先级高于宏任务,可以确保在宏任务执行完毕前立即执行。常见的微任务包括:

  • Promise.then()
  • MutationObserver
  • requestAnimationFrame()

执行顺序和优先级

微任务的优先级高于宏任务。这意味着在事件循环中,微任务会在宏任务之前执行。

示例和 Demo

下面是一个简单的示例来演示宏任务和微任务的执行时机:

javascript 复制代码
console.log('Start');

setTimeout(() => {
  console.log('宏任务');
}, 0);

Promise.resolve().then(() => {
  console.log('微任务');
});

console.log('End');

在浏览器的控制台中运行上述代码,你会看到以下输出:

Linux 复制代码
Start
End
微任务
宏任务

解释:

  • 首先,console.log('Start')console.log('End') 会立即执行,因为它们是同步代码。
  • 然后,Promise.resolve().then(() => { console.log('微任务'); }) 会被添加到微任务队列中,因为它是一个微任务。
  • 接着,setTimeout(() => { console.log('宏任务'); }, 0) 会被添加到宏任务队列中,因为它是一个宏任务。
  • 浏览器会执行事件循环。
  • 在事件循环的第一个步骤中,浏览器会检查是否有待处理的宏任务。发现有,则执行 setTimeout() 函数,输出 宏任务
  • setTimeout() 函数执行之前,浏览器会检查微任务队列。发现有,则执行 Promise.then() 函数,输出 微任务
  • 最后,浏览器会渲染页面。

注意

这说明微任务(Promise)会在宏任务(setTimeout)之前执行。

总结

虽然在 JavaScript 的规范中并没有直接定义宏任务和微任务的概念,但它们是在事件循环机制中的一种抽象描述,有助于我们理解异步任务的执行顺序和优先级。通过合理地利用宏任务和微任务,我们可以更好地管理和优化 JavaScript 代码的执行。

进阶(面试可能加分哦)

事件循环的更多细节

  • 事件循环不止一个,浏览器通常会维护多个事件循环,用于不同的任务类型,例如 DOM 事件、网络请求等。
  • 微任务队列也可能不止一个,不同的微任务队列可能具有不同的优先级。

相关 API

  • setTimeout()setInterval():用于延迟执行任务。
  • Promise:用于处理异步操作。
  • MutationObserver:用于监听 DOM 元素的变化。
  • requestAnimationFrame():用于在浏览器下一次重绘之前执行任务。

参考资料

作为了解

不同浏览器版本和不同的 JavaScript 引擎可能会对事件循环机制的实现细节有所不同。 尽管在 ECMAScript 标准中规定了事件循环的基本机制,但实际上每个浏览器厂商和 JavaScript 引擎开发者都可能根据自己的需求和优化策略进行调整和改进。

这些差异可能会涉及到宏任务和微任务的处理顺序、微任务与宏任务之间的关系、任务队列的管理方式等方面。因此,在编写依赖于事件循环机制的代码时,需要考虑到这些差异,以确保代码在不同环境下的兼容性和稳定性。

通常情况下,浏览器厂商会遵循 ECMAScript 标准,并尽可能保持与其他浏览器的一致性。

相关推荐
LucianaiB14 分钟前
【Dify + EdgeOne】你奶奶也会做一个“智票通”,轻松票据自定义提取+防数据泄露
前端·后端
python在学ing18 分钟前
前端-CSS学习笔记
前端·css·python·学习
nJI74egg119 分钟前
JavaEE初阶---《JUC 并发编程完全指南:组件用法、原理剖析与面试应答》
java·面试·java-ee
Bug-制造者30 分钟前
【Vue3 实战】全局错误处理体系搭建:实现业务与错误彻底解耦
前端·javascript·vue.js
悟空瞎说33 分钟前
# Git 交互式变基:优雅整理提交历史,告别杂乱 PR 记录
前端·git
竹林81843 分钟前
从ethers.js迁移到Viem:我在DeFi Dashboard项目中踩过的坑与最终方案
javascript
还有多久拿退休金1 小时前
DragSortTable:一个让我怀疑人生的滚动重置 Bug
前端
zithern_juejin1 小时前
ES6——Promise
javascript
渐儿1 小时前
组件库开发入门到生产(从零封装到 npm 发布)
前端
KaMeidebaby1 小时前
卡梅德生物技术快报|单 B 细胞抗体制备:流程优化、表达系统适配与性能数据
前端·数据库·其他·百度·新浪微博