了解 Error.captureStackTrace 和堆栈跟踪持久性?

Mar*_*tin 5 error-handling node.js

前段时间我曾经使用来自joyent的Verror在重新抛出时不会丢失堆栈跟踪,我刚刚在没有Verror的情况下使用节点v12进行了测试,并且堆栈跟踪似乎在不使用错误的情况下持续存在。

然后我正在查看 Error.captureStackTrace 的使用,它声明在您的错误中使用它,以便错误不会添加到堆栈中。

我不知道我做错了什么,但有或没有 Error.captureStackTrace - 堆栈跟踪是相同的..

我想知道使用 captureStackTrace 的当前状态,因为我认为没有区别:-) 以及似乎不再需要的 VError 的使用。

在文档中,它指出 .stack 在不调用 captureStackTrace 的情况下不可用,但我每次都看到它可用,无论是否有 captureStackTrace

这是 2 x 错误的示例

class MyErrorOne extends Error {
  constructor(message) {
    super(message);

    Error.captureStackTrace(this, this.constructor);
  }
}

class MyErrorTwo extends Error {
  constructor(message) {
    super(message);

    Error.captureStackTrace(this, this.constructor);
  }
}

Run Code Online (Sandbox Code Playgroud)

我通过在每个错误中注释掉 captureStackTrace 来尝试它们,并且堆栈跟踪是相同的。

任何人都可以帮忙吗?

这是我测试调用错误的代码

const DoOne = () => {
  try {
    console.log("executing do one");
    DoTwo();
  } catch (error) {
    console.log("error in DoOne", error);
    console.log("here is the stack ", error.stack);
    throw new MyErrorOne("threw error from doone in myerrorone");
    // throw error;
  }
};

const DoTwo = () => {
  try {
    console.log("executing do two");
    throw new MyErrorTwo("threw error from dotwo in myerrortwo");
  } catch (error) {
    console.log("error in DoTwo", error);
    throw error;
  }
};

DoOne();
Run Code Online (Sandbox Code Playgroud)

use*_*816 32

调用时,Error.captureStackTrace(obj[, fun])会附加格式化的调用堆栈,包括调用的obj行/帧。captureStackTrace

当指定fun以上所有框架时,包括在内fun将被删除。

例子:

注意:在示例输出中,我删除了以下调用的所有内容,以fun1最大程度地减少混乱。

const fun1 = () => { fun2(); };
const fun2 = () => { fun3(); };
const fun3 = () => { log_stack(); };
function log_stack() {
    let err = {};
    Error.captureStackTrace(err);
    console.log(err.stack);
}
fun1();
Run Code Online (Sandbox Code Playgroud)

这产生:

Error
    at log_stack (/path/to/example.js:6:8)
    at fun3 (/path/to/example.js:3:22)
    at fun2 (/path/to/example.js:2:22)
    at fun1 (/path/to/example.js:1:22)
Run Code Online (Sandbox Code Playgroud)

现在,如果我们将log_stack函数选项添加到captureStackTrace

Error.captureStackTrace(err, log_stack);
Run Code Online (Sandbox Code Playgroud)

它产生:

Error
    at fun3 (/path/to/example.js:3:22)
    at fun2 (/path/to/example.js:2:22)
    at fun1 (/path/to/example.js:1:22)
Run Code Online (Sandbox Code Playgroud)

框架log_stack已经不存在了。

添加fun3captureStackTrace

Error.captureStackTrace(err, fun3);
Run Code Online (Sandbox Code Playgroud)

它产生:

Error
    at fun2 (/path/to/example.js:2:22)
    at fun1 (/path/to/example.js:1:22)
Run Code Online (Sandbox Code Playgroud)

ETC。

在你的情况下,如果你改变:

Error.captureStackTrace(this, this.constructor);
Run Code Online (Sandbox Code Playgroud)

到:

Error.captureStackTrace(this);
Run Code Online (Sandbox Code Playgroud)

您会看到多了一行new MyError...

error in DoTwo MyErrorTwo: threw error from dotwo in myerrortwo
    at new MyErrorTwo (/path/to/testerrorclass.js:10:9)  <<== Not removed anymore.
Run Code Online (Sandbox Code Playgroud)


小智 9

我不确定,但似乎Error.captureStackTrace打算在构造 Error 对象而不扩展类时使用(另请参阅Node 文档Error中提供的示例)。

我猜测当您扩展该类时Error,错误构造函数已经完成了捕获堆栈跟踪。

我已经测试了您的代码并删除了 Error 的扩展,实际上,如果您不调用,captureStackTrace您将不会获得错误对象的堆栈跟踪。

我不确定抛出不扩展 Error 类的错误的用例是什么。