likes
comments
collection
share

JavaScript 没有宏任务和微任务在 JavaScript 中,宏任务和微任务的概念是建立在事件循环机制之上的一种

作者站长头像
站长
· 阅读数 27

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

事件循环机制

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

事件循环是一个不断循环的过程,它的运行步骤如下:

  1. 从堆栈中取出待执行的任务并执行
  2. 检查微任务队列,如果有任务,则依次执行微任务队列中的所有任务,直至队列为空
  3. 检查是否有宏任务需要执行,如果有,则从宏任务队列中取出一个执行,执行完成后回到步骤2,否则继续等待新的宏任务到达
  4. 渲染页面

JavaScript 没有宏任务和微任务在 JavaScript 中,宏任务和微任务的概念是建立在事件循环机制之上的一种

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

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

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

微任务(Microtask)指的是通过"queue a microtask"算法创建的任务。根据W3C HTML规范,每个事件循环都有一个专门的微任务队列,用于存储这些通过算法创建的微任务。这些微任务会在当前宏任务执行完毕后立即执行,它们的优先级高于宏任务

  • Promise.then()
  • MutationObserver

执行顺序和优先级

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

示例和 Demo

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

console.log('Start');

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

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

console.log('End');

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

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

转载自:https://juejin.cn/post/7344993022075469874
评论
请登录