异步执行顺序
finally 与 then 的注册顺序如何影响输出?
Promise.resolve("1")
.then((res) => console.log(res))
.finally(() => console.log("finally"));
Promise.resolve("2")
.finally(() => {
console.log("finally2");
return "我是 finally2 返回的值"; // finally 的返回值被忽略
})
.then((res) => console.log("finally2 后面的 then", res));
// 1
// finally2
// finally
// finally2 后面的 then 2
- 规律: 每个
then/finally注册为一个微任务, 按注册顺序入队;finally不改变链上的值;
async、await、setTimeout 与 Promise 交错时如何阅读?
const async1 = async () => {
console.log("async1 start");
await async2();
console.log("async1 end");
};
const async2 = () => console.log("async2");
console.log("script start");
setTimeout(() => console.log("setTimeout"), 0);
async1();
new Promise((resolve) => {
console.log("promise1");
resolve(1);
console.log("resolve after");
}).then(() => console.log("promise2"));
console.log("script end");
// script start
// async1 start
// async2
// promise1
// resolve after
// script end
// async1 end
// promise2
// setTimeout
- 步骤:
- 同步代码依次执行:
script start、async1 start、async2, 遇到await让出, 把恢复任务入微任务队列; - 进入 Promise 构造器同步执行
promise1、resolve(1)、resolve after,then回调入微任务队列; - 打印
script end, 同步代码结束; - 清空微任务队列: 先恢复
async1打印async1 end, 再执行promise2; - 宏任务队列中的
setTimeout最后执行;
- 同步代码依次执行:
await 链与宏任务交错时如何阅读?
const sleep = async () =>
new Promise((resolve) => {
console.log("sleep before");
setTimeout(resolve, 1000);
}).then(() => console.log("sleep after"));
const fn = async () => {
console.log("fn");
await sleep();
return null;
};
async function foo() {
console.log(2);
console.log(await fn());
console.log(4);
}
console.log(1);
foo().then(() => console.log("end"));
console.log(3);
// 1
// (foo) 2
// (fn) fn
// (sleep) sleep before
// 3
// —— 1s 后恢复 ——
// sleep after
// null
// 4
// end
- 阅读方法: 先执行到最内层
await的同步部分, 再逐层把恢复任务推入微任务队列; 计时器到时后从宏任务恢复整条 await 链;