const myPromise = Promise.resolve(Promise.resolve("Promise!"));
function funcOne() {
myPromise.then((res) => res).then((res) => console.log(res));
setTimeout(() => console.log("Timeout!"), 0);
console.log("Last line!");
}
async function funcTwo() {
const res = await myPromise;
console.log(await res);
setTimeout(() => console.log("Timeout!"), 0);
console.log("Last line!");
}
funcOne();
funcTwo();
// 2023-03-04 更新解析
首先,我们调用 funcOne
。
在函数 funcOne
的第一行,我们调用myPromise
promise 异步操作。当JS引擎在忙于执行 promise,它继续执行函数 funcOne
。下一行 异步操作 setTimeout
,其回调函数被 Web API 调用。
promise 和 timeout 都是异步操作,函数继续执行当JS引擎忙于执行 promise 和 处理 setTimeout
的回调。相当于 Last line!
首先被输出, 因为它不是异步操作。
执行完 funcOne
的最后一行,继续往后执行 funcTwo
,但 funcTwo
函数内部第一行就是 await
阻止了后面代码的执行,所以才会去执行funcOne
中myPromise
的第一个then
。funcOne
中第一行的 promise
状态转变为 resolved,Promise!
被打印。
然而,我们调用了 funcTwo()
, 调用栈不为空,setTimeout
的回调仍不能入栈。
我们现在处于 funcTwo
,先 awaiting myPromise。通过 await
关键字, 我们暂停了函数的执行直到 promise 状态变为 resolved (或 rejected)。然后,我们输出 res
的 awaited 值(因为 promise 本身返回一个 promise)。 接着输出 Promise!
。
下一行就是 异步操作 setTimeout
,其回调函数被 Web API 调用。
我们执行到函数 funcTwo
的最后一行,输出 Last line!
。现在,因为 funcTwo
出栈,调用栈为空。在事件队列中等待的回调函数(() => console.log("Timeout!")
from funcOne
, and () => console.log("Timeout!")
from funcTwo
)以此入栈。第一个回调输出 Timeout!
,并出栈。然后,第二个回调输出 Timeout!
,并出栈。得到结果 Last line! Promise! Promise! Last line! Timeout! Timeout!
大家还可以想想,下面会输出什么:
const myPromise = Promise.resolve(Promise.resolve("Promise!"));
function funcOne() {
myPromise
.then((res) => {
console.log("执行第一个then", res);
return res;
})
.then((res) => {
console.log("执行第二个then", res);
});
setTimeout(() => console.log("Timeout!"), 0);
console.log("Last line!");
}
async function funcTwo() {
console.log("进入funcTwo");
const res = await myPromise;
console.log("执行完第一个await,继续往下执行");
console.log(await res);
console.log("执行完第二个await,继续往下执行");
setTimeout(() => console.log("Timeout!"), 0);
console.log("Last line!");
}
funcOne();
funcTwo();