async 函数优雅的处理错误
·
Yin灏
如果 await 后面的异步操作出错,那么等同于 async 函数返回的 Promise 对象被 reject。
async function f() {
await new Promise(function (resolve, reject) {
throw new Error("出错了");
});
}
f()
.then((v) => console.log(v))
.catch((e) => console.log(e));
// Error:出错了
上面代码中,async 函数 f 执行后,await 后面的 Promise 对象会抛出一个错误对象,导致 catch 方法的回调函数被调用,它的参数就是抛出的错误对象。
任何一个 await 语句后面的 Promise 对象变为 reject 状态,那么整个 async 函数都会中断执行。
async function f() {
await Promise.reject("出错了");
await Promise.resolve("hello world"); // 不会执行
}
上面代码中,第二个 await 语句是不会执行的,因为第一个 await 语句状态变成了 reject。
有时,我们希望即使前一个异步操作失败,也不要中断后面的异步操作。这时可以将第一个 await 放在 try…catch 结构里面,这样不管这个异步操作是否成功,第二个 await 都会执行。
async function f() {
try {
await Promise.reject("出错了");
} catch (e) {}
return await Promise.resolve("hello world");
}
f().then((v) => console.log(v));
// hello world
另一种方法是 await 后面的 Promise 对象再跟一个 catch 方法,处理前面可能出现的错误。
async function f() {
await Promise.reject("出错了").catch((e) => console.log(e));
return await Promise.resolve("hello world");
}
f().then((v) => console.log(v));
// 出错了
// hello world
如果有多个 await 命令,可以统一放在 try…catch 结构中。
如果不想使用 try…catch 结构,你可以通过错误优先的方式方式统一处理结果。
async function f() {
await fetch("/api/list")
.then((data) => [null, data])
.catch((err) => [err, undefined]);
}
async function main() {
const [err, data] = await f();
if (!err) {
return await Promise.resolve("hello world");
}
}
数组之中有两个元素,如果索引为 0 的元素不为空值,说明该请求报错,如果索引 0 的元素为空值说明该请求没有报错,也就是成功。