Promise
Promise 是一个表示异步操作最终完成或失败的对象。它有三个状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。Promise 是异步执行的,但是它的回调函数(then、catch、finally)会按照代码中的顺序放入微任务队列(microtask queue),并在当前执行栈(execution context)为空时执行。
async 和 await
async 函数是使用 async 关键字声明的函数。这样的函数返回一个 Promise 对象。await 关键字用于等待 Promise 完成,它只能在 async 函数内部使用。当 await 被调用时,它会暂停 async 函数的执行,直到 Promise 被解决或拒绝,然后继续执行 async 函数。
setTimeout
setTimeout 是一个全局函数,它用来在指定的毫秒数后执行一个函数或一段代码。setTimeout 将其回调函数放入宏任务队列(macrotask queue),在事件循环的下一个循环中执行。
执行顺序
- JavaScript 引擎首先执行同步代码,包括
async函数的声明和setTimeout的调用。 - 当遇到
await关键字时,它会异步等待Promise解决,并允许其他同步代码继续执行。 - 如果
Promise快速解决,它的回调(如果有await,则是await之后的代码)将被作为微任务添加到微任务队列中。 setTimeout的回调会在指定的时间后被添加到宏任务队列中。- 当前执行栈为空时,事件循环将首先处理微任务队列中的所有微任务。
- 微任务队列清空后,事件循环会检查宏任务队列,并按顺序执行其中的宏任务。
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
});
console.log('script end');
执行结果:
script start
script end
promise1
promise2
setTimeout
解释:
- 首先,同步代码
script start和script end被打印。 setTimeout的回调被添加到宏任务队列。Promise的第一个.then()被添加到微任务队列。- 当执行栈为空时,微任务队列中的
promise1和promise2被执行。 - 微任务队列清空后,事件循环处理宏任务队列中的
setTimeout回调。
由于浏览器或JavaScript引擎的实现差异,Promise 和 setTimeout 的确切执行时机可能会有所不同。