JS-Promise、微任务和宏任务,跟我一起搞明白
2024-02-07 22:28:37
前言
在现代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的微任务处理机制使得我们可以更方便地处理异步操作,并编写更健壮、更可控的异步代码。