本文探讨JavaScript中async await的错误处理方案。针对传统try...catch在多处异步调用时的冗余问题,介绍利用await-to-js库将错误与结果封装为数组的优雅处理方式,通过解构赋值简化代码逻辑,提升异步编程的可读性与维护性。
背景
团队新成员注意到代码规范要求对 async await 添加 try...catch 块,对此感到困惑:若异步调用分散且数量较多,需在各处添加捕获逻辑,这显得不够优雅。
为什么要错误处理
JavaScript 为单线程语言,若未进行异常捕获,程序会直接报错并中断执行。使用 try...catch 并非强制要求,而是表明开发者预判该处代码可能抛出异常,通过捕获处理使程序得以继续运行。
在异步场景下执行 async await 时,通常不希望流程被阻塞,因此推荐使用 try...catch 进行错误处理。
async await 更优雅的错误处理
正如同事所言,大量使用 try...catch 确实不够优雅。经查阅 How to write async await without try-catch blocks in Javascript 一文,发现一种更优方案,并已封装为 await-to-js 库。该库仅包含一个函数,可直接应用于业务代码,示例如下:
/**
* @param { Promise } promise
* @param { Object= } errorExt - Additional Information you can pass to the err object
* @return { Promise }
*/
export function to<T, U = Error> (
promise: Promise<T>,
errorExt?: object
): Promise<[U, undefined] | [null, T]> {
return promise
.then<[null, T]>((data: T) => [null, data]) // 执行成功,返回数组第一项为 null。第二个是结果。
.catch<[U, undefined]>((err: U) => {
if (errorExt) {
Object.assign(err, errorExt);
}
return [err, undefined]; // 执行失败,返回数组第一项为错误信息,第二项为 undefined
});
}
export default to;
需明确前置知识:await 用于等待 Promise 的返回值。
通常,await 后接 Promise 对象并返回其结果;若非 Promise 对象,则直接返回对应值。
利用 Promise 特性,可在 promise.then 和 promise.catch 中分别返回不同数组:成功时返回 [null, result],失败时返回 [error, undefined]。使用时只需判断数组第一项是否为 null 即可知晓是否出错,具体用法如下:
import to from 'await-to-js';
// If you use CommonJS (i.e NodeJS environment), it should be:
// const to = require('await-to-js').default;
async function asyncTaskWithCb(cb) {
let err, user, savedTask, notification;
[ err, user ] = await to(UserModel.findById(1));
if(!user) return cb('No user found');
[ err, savedTask ] = await to(TaskModel({userId: user.id, name: 'Demo Task'}));
if(err) return cb('Error occurred while saving task');
if(user.notificationsEnabled) {
[ err ] = await to(NotificationService.sendNotification(user.id, 'Task Created'));
if(err) return cb('Error while sending notification');
}
if(savedTask.assignedUser.id !== user.id) {
[ err, notification ] = await to(NotificationService.sendNotification(savedTask.assignedUser.id, 'Task was created for you'));
if(err) return cb('Error while sending notification');
}
cb(null, savedTask);
}
小结
在 async await 中添加错误处理确有必要,但方案不限于 try...catch。结合 async await 与 Promise 特性,可实现更优雅的异步错误处理机制。
总结
本文介绍了 JavaScript 中 async await 的优雅错误处理方式,更多相关内容请参考本站过往文章或继续浏览后续内容,感谢支持。