繁体   English   中英

JavaScript / TypeScript:保留错误原因的标准方法

[英]JavaScript / TypeScript : Standard way to keep the cause of an Error

我有 Java 开发人员的背景,我对 JavaScript/TypeScript 很陌生。

是否有一种标准方法来管理和保留 JavaScript/TypeScript 中的错误原因?

我的目的是在将错误包装到另一个错误时获得完整的堆栈跟踪; 有点像 Java 异常堆栈跟踪:

Message of exception 1
...
Caused by: Message of exception 2
...
Caused by: Message of the root exception

我尝试了这段代码,但err1没有保留err2的引用:

// CODE
try {
    try {
        throw new Error("Error no2");
    } catch (err2) {
        console.log("========================================");
        console.log(err2);
        throw new Error("Error no1");
    }
} catch (err1) {
    console.log("========================================");
    console.log(err1);
}
// CONSOLE OUTPUT
$ node test.ts 
========================================
Error: Error no2
    at Object.<anonymous> (/tmp/test.ts:3:15)
    at Module._compile (internal/modules/cjs/loader.js:956:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:973:10)
    at Module.load (internal/modules/cjs/loader.js:812:32)
    at Function.Module._load (internal/modules/cjs/loader.js:724:14)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1025:10)
    at internal/main/run_main_module.js:17:11
========================================
Error: Error no1
    at Object.<anonymous> (/tmp/test.ts:7:15)
    at Module._compile (internal/modules/cjs/loader.js:956:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:973:10)
    at Module.load (internal/modules/cjs/loader.js:812:32)
    at Function.Module._load (internal/modules/cjs/loader.js:724:14)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1025:10)
    at internal/main/run_main_module.js:17:11

此外,我没有在错误 class 中找到任何名为cause的属性。有一个stack属性,但我认为更改它是一种不好的做法。

谢谢!

我一直在这里使用克里斯蒂安答案的修改

class TraceableError extends Error {
  trace: Error;

  constructor(message?: string, innerError?: Error) {
    super(message); 
    this.trace = innerError;

    const actualProto = new.target.prototype;

    if (Object.setPrototypeOf) { Object.setPrototypeOf(this, actualProto); } 
    else { this.__proto__ = actualProto; } 
  }
}

然后你会像这样扔

try {
    try {
        throw new Error("Error no2");
    } catch (err2) {
        console.log("========================================");
        console.log(err2);
        throw new TraceableError ("Error no1", err2);
    }
} catch (err1) {
    console.log("========================================");
    console.log(err1);
}

注意,如果没有捕获,新错误的trace部分不会输出到控制台。

2021 答案:现在有一种标准的方法来管理和保持错误的原因。 Error()构造函数现在可以接受一个options对象作为第二个参数。 这个options对象应该有一个cause属性,它通常是另一个Error但它不一定是。

例子

throw new Error('Outer Error', {cause: new Error('Inner Error')});

支持

在撰写本文时(2021 年 10 月),Firefox、Chrome 和 Safari 支持新的构造函数。 要获得Error的原因,您需要询问它的cause属性。 此外,在 Firefox 中,我们会在控制台中获得一些额外信息,例如

Uncaught Error: Outer Error
    <anonymous> debugger eval code:1
Caused by: Error: Inner Error
    <anonymous> debugger eval code:1

Edge 目前将忽略第二个构造函数属性。

来源

Mozilla 文档: https : //developer.mozilla.org/en-US/docs/web/javascript/reference/global_objects/error

ECMAScript 提案: https : //github.com/tc39/proposal-error-cause

我经常使用错误原因选项。 记录器使用的我的文本构建 function 看起来像这样

export function getErrorMessageWithCausedByParts(err: Error, stack=true): string {
  const doNewLines = stack;
  let txt = "";
  
  if(stack) {
    txt+=err.stack;
  } else {
    txt+=err.message;
  }

  if(err.cause != null) {
    if (err.cause instanceof Error) {
      if(doNewLines) {
        txt+="\n[caused by] ";
      } else {
        txt += " [caused by] ";
      }
      
      txt += getErrorMessageWithCausedByParts(err.cause, stack);
    } else {
      txt += `[Unknown cause type?!]: ${JSON.stringify(err.cause)}`
    }
  }

  return txt;
}

注意:为了能够使用错误 object 的原因选项,您必须在 tsconfig.json 中设置更新的 ES 版本

"compilerOptions": {

    "lib": ["es2022"]

    ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM