Promise异步编程的深入剖析
2024-02-15 00:22:29
深入理解Promise
Promise是JavaScript中用于处理异步编程的强大工具。它允许您将异步操作包装成一个对象,并提供一系列方法来处理其结果。
Promise有三种状态:
- Pending: 初始状态,表示异步操作尚未完成。
- Fulfilled: 成功状态,表示异步操作已成功完成。
- Rejected: 失败状态,表示异步操作已失败。
您可以使用then()
方法来处理Promise的结果。then()
方法接受两个参数:一个成功回调函数和一个失败回调函数。当Promise的状态变为Fulfilled
时,将调用成功回调函数;当Promise的状态变为Rejected
时,将调用失败回调函数。
Promise与微任务
Promise与微任务之间存在着紧密的关系。微任务是JavaScript引擎在执行宏任务(如事件循环)之前执行的一组任务。微任务队列是存储微任务的地方,当微任务队列不为空时,JavaScript引擎会首先执行微任务队列中的所有任务,然后才会执行宏任务队列中的任务。
Promise的状态改变时,会将一个微任务添加到微任务队列中。这个微任务会执行Promise的回调函数,并将结果传递给下一个then()
方法。
不同类型异步代码的执行顺序
Promise + 定时器
console.log('start');
setTimeout(() => {
console.log('timer');
}, 0);
Promise.resolve().then(() => {
console.log('promise');
});
console.log('end');
输出:
start
promise
end
timer
在这个示例中,console.log('start')
首先执行,然后Promise被解析,并添加一个微任务到微任务队列。接下来,console.log('end')
执行。由于微任务队列不为空,所以JavaScript引擎会在执行宏任务(定时器)之前执行微任务队列中的所有任务,因此console.log('promise')
被执行。最后,定时器被执行,console.log('timer')
被输出。
纯Promise
console.log('start');
Promise.resolve().then(() => {
console.log('promise1');
});
Promise.resolve().then(() => {
console.log('promise2');
});
console.log('end');
输出:
start
promise1
promise2
end
在这个示例中,console.log('start')
首先执行,然后两个Promise被解析,并分别添加一个微任务到微任务队列。接下来,console.log('end')
执行。由于微任务队列不为空,所以JavaScript引擎会在执行宏任务(定时器)之前执行微任务队列中的所有任务,因此console.log('promise1')
和console.log('promise2')
被执行。
await + Promise
async function main() {
console.log('start');
await Promise.resolve();
console.log('promise');
console.log('end');
}
main();
输出:
start
promise
end
在这个示例中,console.log('start')
首先执行,然后await Promise.resolve()
暂停main()
函数的执行,并添加一个微任务到微任务队列。接下来,console.log('end')
执行。由于微任务队列不为空,所以JavaScript引擎会在执行宏任务(定时器)之前执行微任务队列中的所有任务,因此console.log('promise')
被执行。最后,main()
函数恢复执行,并输出console.log('end')
。
nextTick + Promise (Node.js)
console.log('start');
process.nextTick(() => {
console.log('nextTick');
});
Promise.resolve().then(() => {
console.log('promise');
});
console.log('end');
输出:
start
nextTick
promise
end
在这个示例中,console.log('start')
首先执行,然后process.nextTick()
将一个回调函数添加到nextTick队列。接下来,console.log('end')
执行。由于nextTick队列不为空,所以Node.js会在执行宏任务(定时器)之前执行nextTick队列中的所有任务,因此console.log('nextTick')
被执行。最后,Promise被解析,并添加一个微任务到微任务队列。由于微任务队列不为空,所以JavaScript引擎会在执行宏任务(定时器)之前执行微任务队列中的所有任务,因此console.log('promise')
被执行。
结论
通过对Promise与微任务关系的深入理解,我们可以更加轻松地编写出简洁、易于维护的异步代码。Promise可以帮助我们避免回调地狱,并使代码更具可读性。