嵌套函数中追加新信息并重抛错误的JavaScript实现方案咨询
解决方案
方案1:基于ES2022标准的cause属性实现(推荐)
这是JavaScript原生支持的通用方案,不需要针对新增错误类型修改上层逻辑,维护成本极低。
核心思路是把原始错误作为上层错误的cause属性传入,也可以选择把原始错误的自定义属性直接合并到上层错误中,避免信息丢失:
// 改造ThirdError构造函数,支持传入原始错误作为cause class ThirdError extends Error { constructor(msg, extraInfo, cause) { // 原生支持cause参数,会自动挂载到this.cause,低版本环境可以省略super的第二个参数手动挂载 super(msg, { cause }); this.arg = extraInfo; // 可选:把原始错误的可枚举属性直接合并到当前错误,方便直接访问 if (cause) { Object.assign(this, cause); } } } // third函数不需要任何类型判断,新增任意错误类型都不用修改此处逻辑 function third(fn) { try { fn(25); } catch (error) { throw new ThirdError('Third error', fn, error); } }
使用时可以完整拿到所有层级的错误信息:
try { third(first); } catch (error) { console.log(error.num); // 25,直接访问原始FirstError的自定义属性 console.log(error.cause instanceof FirstError); // true,保留原始错误类型判断 console.log(error instanceof ThirdError); // true,上层错误类型判断也保留 console.log(error.stack); // 堆栈信息会完整包含原始错误和上层错误的调用链路 }
方案2:直接扩展原始错误(适合需要保留原始错误类型判断的场景)
如果不需要区分错误是在哪一层抛出的,只需要追加额外信息,可以直接修改原始错误后抛出,完全保留原始错误的所有特征:
function third(fn) { try { fn(25); } catch (error) { // 直接给原始错误追加额外信息,不生成新的错误实例 error.thirdArg = fn; error.message = `Third error: ${error.message}`; // 也可以追加错误消息 throw error; } }
使用时完全保留原始错误的类型判断:
try { third(first); } catch (error) { console.log(error instanceof FirstError); // true,原始类型判断不受影响 console.log(error.num); // 25,原有属性全部保留 console.log(error.thirdArg); // 追加的属性可以正常访问 }
内容的提问来源于stack exchange,提问作者cj-2307
相关产品推荐
相关产品推荐

