一、背景
宏任务(宿主环节浏览器和node发起的任务):整体代码script、setTimeout、setInterval、MessageChannel、postMessage、setImmediate(node)。
微任务(JavaScript引擎本身发起任务):Promise、async/await、process.nextTick(node api)、MutationObsever。
二、await返回promise
执行顺序:
若await后是promise,立即执行同步代码,把then回调函数放入微任务队列,然后执行async函数外部的代码。若没有then回调函数,把await后面的代码放入微任务队列,继续执行async函数外部的代码。
async function async1() {
console.log("1");
await new Promise((resolve) => {
console.log("2");
resolve();
}).then(() => {
console.log("3");
});
console.log("4");
}
async1();
console.log("5");
new Promise((resolve) => {
console.log("6");
resolve();
}).then(() => {
console.log("7");
});
setTimeout(() => {
console.log("8");
}, 0);
console.log("9");
输出结果:1,2,5,6,9,3,7,4,8
async function async1() {
console.log("1");
await new Promise((resolve) => {
console.log("2");
resolve();
});
console.log("4");
}
async1();
console.log("5");
new Promise((resolve) => {
console.log("6");
resolve();
}).then(() => {
console.log("7");
});
setTimeout(() => {
console.log("8");
}, 0);
console.log("9");
输出:1,2,5,6,9,4,7,8
三、async中断执行
语法:任何一个await语句后面的 Promise 对象变为reject状态,那么整个async函数都会中断执行。
async function f() {
await Promise.reject("出错了"); //这里如果在await前面加上return,效果是一样的。
await Promise.resolve("hello world"); // 不会执行
}
f()
.then((v) => console.log("then", v))
.catch((e) => console.log("catch",e));
输出:
catch 出错了
async function f() {
await new Promise((resolve, reject) => {
console.log("run");
reject("出错了");
});
await Promise.resolve("hello world"); // 不会执行
}
f()
.then((v) => console.log("then", v))
.catch((e) => console.log("catch",e));
输出:
run
catch 出错了
3.1 解决方案
方法一:
async function f() {
try {
await Promise.reject("出错了");
} catch (e) {
console.log("inner:", e);
}
return await Promise.resolve("hello world"); // 要加return,否则返回undefined
}
f()
.then((v) => console.log("then", v))
.catch((e) => console.log("catch", e));
输出:
inner: 出错了
then hello world
方法二:
async function f() {
await Promise.reject("出错了").catch((e) => console.log("inner:", e));
return await Promise.resolve("hello world");
}
f()
.then((v) => console.log("then", v))
.catch((e) => console.log("catch", e));
输出
inner: 出错了
then hello world