返回

JS-Promise、微任务和宏任务,跟我一起搞明白

前端

前言

在现代Web开发中,我们经常需要处理异步操作,比如网络请求、定时器、DOM事件等。这些异步操作的特点是,它们不会立即返回结果,而是需要一段时间后才能完成。为了处理这些异步操作,JavaScript提供了Promise、微任务和宏任务等机制。

Promise

Promise是一个JavaScript对象,它代表一个异步操作的最终完成或失败及其结果值。Promise对象有三个状态:pending(等待)、fulfilled(完成)和rejected(失败)。当异步操作完成时,Promise对象的状态会变成fulfilled,此时可以调用then方法来获取操作结果。如果异步操作失败,Promise对象的状态会变成rejected,此时可以调用catch方法来处理错误。

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('成功!');
  }, 1000);
});

promise.then((result) => {
  console.log(result); // 输出:成功!
});

微任务和宏任务

微任务和宏任务都是JavaScript中的任务队列,它们用来存储需要执行的任务。微任务队列的优先级高于宏任务队列,这意味着微任务队列中的任务会优先执行。

微任务

微任务队列中的任务包括:

  • Promise对象的then方法
  • MutationObserver回调函数
  • DOM事件回调函数
  • requestAnimationFrame回调函数

宏任务

宏任务队列中的任务包括:

  • setTimeout和setInterval的回调函数
  • I/O操作(如网络请求)
  • script标签的执行
  • DOMContentLoaded事件

Promise的微任务处理机制

当一个Promise对象的状态从pending变成fulfilled或rejected时,JavaScript引擎会将一个微任务添加到微任务队列中。这个微任务会在当前宏任务执行结束后执行,并调用Promise对象的then方法或catch方法。

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('成功!');
  }, 1000);
});

promise.then((result) => {
  console.log(result); // 输出:成功!
});

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

在这个例子中,虽然宏任务setTimeout的执行时间早于Promise的微任务,但由于微任务的优先级更高,所以微任务会先执行,输出结果为“成功!”,然后才是宏任务,输出结果为“宏任务”。

宏任务的提升误解

有些人可能会误认为,宏任务也可以提升到微任务队列中执行。但实际上,这是不正确的。宏任务只能在微任务队列执行完毕后才能执行。

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

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

在这个例子中,虽然setTimeout的宏任务执行时间早于Promise的微任务,但由于微任务的优先级更高,所以微任务会先执行,输出结果为“微任务”,然后才是宏任务,输出结果为“宏任务”。

Promise的应用场景

Promise可以用于处理各种异步操作,常见场景包括:

  • 网络请求
  • 定时器
  • DOM事件
  • 文件操作
  • 动画

总结

Promise、微任务和宏任务是JavaScript中处理异步操作的重要机制。Promise对象可以表示一个异步操作的最终完成或失败及其结果值。微任务队列的优先级高于宏任务队列,这意味着微任务队列中的任务会优先执行。Promise的微任务处理机制使得我们可以更方便地处理异步操作,并编写更健壮、更可控的异步代码。