JS异步函数中如何在catch块返回已有自定义错误,无需抛出新错误
如何在catch块中传递原有自定义错误对象、无需重复构造新错误实例
问题场景
现有代码的核心诉求是:上层callSomething函数需要在catch块中拿到携带附加属性的自定义ApiError实例,传入customErrorTreatment做统一错误处理。
代码结构如下:
- 外层调用逻辑
const callSomething = async () => { try { doSomething(); } catch (error) { // 需要拿到带附加属性的自定义错误对象做统一处理 customErrorTreatment(error); } };
- 被调用的
doSomething函数目前的两种试错方案都存在问题:
const doSomething = async () => { try { // 此处会抛出带附加属性的自定义错误类实例 throwApiError({ responseMessage: 'Some error occour', responseStatus: 500, }); } catch (error) { // 方案1:直接return捕获的error // 问题:上层会将这个值当作普通返回值,不会进入catch分支 return error; // 方案2:重新构造新的错误实例抛出 // 问题:重复构造逻辑冗余,写法丑陋,还容易出现属性映射错误 return throwApiError({ responseMessage: error.responseMessage, responseStatus: error.status, }); } };
- 底层自定义错误与抛出辅助函数实现
// 带附加属性的自定义错误类 export const ApiError = class ApiError extends Error { constructor({ responseMessage, responseStatus, error }) { super(error); this.responseMessage = responseMessage; this.responseStatus = responseStatus; } }; // 抛出自定义错误的辅助函数 const throwApiError = ({ responseMessage, responseStatus, error }) => { throw new ApiError({ responseMessage, responseStatus}); };
核心实现方案
完全不需要重新构造新的错误实例,只需要遵循JS的错误传递规则处理即可:
- 在catch块中
return任意值,都会被异步函数当作正常resolved的返回值,上层走then分支,不会触发catch捕获 - 要让上层进入catch分支拿到错误,只需要把已经捕获到的原有error对象直接抛出即可,所有附加属性都会完整保留。
正确写法
修改doSomething的catch块逻辑,直接抛出原有捕获的错误对象:
const doSomething = async () => { try { throwApiError({ responseMessage: 'Some error occour', responseStatus: 500, }); } catch (error) { // 直接抛出原有错误实例,无需重新构造 throw error; } };
这种写法的优势:
- 完全复用原有的ApiError实例,无冗余的对象构造开销
- 错误上携带的
responseMessage、responseStatus等自定义属性完整保留,上层拿到的对象和原始抛出的实例完全一致 - 逻辑无冗余,代码简洁
进一步优化
如果doSomething的内部try-catch没有做额外的日志记录、错误信息补充等自定义逻辑,可以直接删除这个冗余的try-catch块,让错误顺着调用栈自动向上冒泡,连手动抛出的步骤都可以省略:
// 最简实现:无冗余try-catch,错误自动向上传递 const doSomething = async () => { throwApiError({ responseMessage: 'Some error occour', responseStatus: 500, }); };
注:之前尝试重新构造错误的写法本身存在属性映射错误——原ApiError实例上的自定义字段是
responseStatus,并非status,这种写法本身就会导致错误属性丢失,属于额外的bug。
内容的提问来源于stack exchange,提问作者Danilo Cunha
相关产品推荐
相关产品推荐

