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 标准,并尽可能保持与其他浏览器的一致性。

相关推荐
wearegogog1231 小时前
基于 MATLAB 的卡尔曼滤波器实现,用于消除噪声并估算信号
前端·算法·matlab
Drawing stars1 小时前
JAVA后端 前端 大模型应用 学习路线
java·前端·学习
品克缤1 小时前
Element UI MessageBox 增加第三个按钮(DOM Hack 方案)
前端·javascript·vue.js
小二·1 小时前
Python Web 开发进阶实战:性能压测与调优 —— Locust + Prometheus + Grafana 构建高并发可观测系统
前端·python·prometheus
小沐°1 小时前
vue-设置不同环境的打包和运行
前端·javascript·vue.js
qq_419854052 小时前
CSS动效
前端·javascript·css
烛阴2 小时前
3D字体TextGeometry
前端·webgl·three.js
桜吹雪2 小时前
markstream-vue实战踩坑笔记
前端
好好沉淀2 小时前
1.13草花互动面试
面试·职场和发展
南村群童欺我老无力.3 小时前
Flutter应用鸿蒙迁移实战:性能优化与渐进式迁移指南
javascript·flutter·ci/cd·华为·性能优化·typescript·harmonyos