About Error.captureStackTrace

created at 07-05-2021 views: 1

introduction

In some Node.js programs, you sometimes see the statement Error.captureStackTrace() to process stack information. What is the standard definition of this sentence? how to use? This article will do some discussion on these issues.

definition of captureStackTrace

Literally, captureStackTrace should be a method of the Error constructor itself. Therefore, it is natural to think of finding the answer from the ECMAScript standard document. Unfortunately, in the 19.5 Error Objects section of the standard document, there is no mention of anything about captureStackTrace. It seems that this statement is related to the operating environment of the language and is not defined by the JavaScript standard.

Since captureStackTrace is not defined in the JavaScript language standard, the answer can only be found in the Node.js documentation. In Node.js, the description of Error.captureStackTrace is like this:

Error.captureStackTrace(targetObject[, constructorOpt])
Add a .stack attribute to targetObject. When accessing this property, it will return the code location information when the Error.captureStackTrace() statement is called (ie: call stack history) in the form of a string.

The following is the simplest example:

const myObject = {};
Error.captureStackTrace(myObject);
myObject.stack // The effect is similar to `new Error().stack`
Unlike `errorObject.stack`, the first line of the string returned by `errorObject.stack` generally follows the form of `ErrorType: message`, while the first line of the string obtained by using captureStackTrace generally begins with ` at the beginning of targetObject .toString()`.

In addition to targetObject, captureStackTrace also accepts an optional parameter constructorOpt of type function. When this parameter is passed, the information above all constructorOpt functions in the call stack (including the constructorOpt function itself) will be ignored when accessing targetObject.stack. The constructorOpt parameter can be useful when you need to hide the internal technical details from the end user. such as:

function MyError() {
   Error.captureStackTrace(this, MyError);
}

// If the MyError parameter is not passed to captureStackTrace, when accessing the .stack property, MyError and its internal information will appear in the stack information. When the MyError parameter is passed, this information will be ignored.
new MyError().stack

Further investigation found that Error.captureStackTrace() was not created by Node.js, but was derived from the Stack Trace API of the V8 engine (in fact, in the Error class of Node.js, all content related to stack trace depends on V8 Stack Trace API). Syntactically speaking, Error.captureStackTrace() in Node.js is exactly the same as the interface exposed in the V8 engine.

In the browser field, except for Google Chrome that uses the V8 engine, the Error.captureStackTrace() interface does not exist in other browsers.

use cases

Because Error.captureStackTrace() can return call stack information, this function is often used in custom Error classes to add reasonable stack attributes to the error object. The MyError class above is the simplest example.

In order not to expose the internal details of the custom Error class to users, when using captureStackTrace inside the custom Error class, the constructorOpt parameter is often passed in, and its value is the constructor of the custom Error class. There are 3 specific methods:

  1. Error.captureStackTrace(this, MyError); Pass in the variable name of the constructor as the constructorOpt parameter. This approach is relatively simple and direct, but the disadvantages are also obvious: what the code wants to convey is "ignore the stack call information inside the current constructor", and passing in the specific constructor as a parameter makes this statement lack of generality , Is not conducive to further abstraction of the program.
  2. Error.captureStackTrace(this, this.constructor); Pass in the constructorOpt parameter through this.constructor. Compared with the previous method, this method is more versatile. This method is recommended when using captureStackTrace in a custom Error class.
  3. Error.captureStackTrace(this, arguments.callee); Pass the "current function" as the constructorOpt parameter through arguments.callee. However, since arguments.callee is disabled in ES5's strict mode, this method is not recommended.

In addition to the usage scenarios of the custom Error class, in JavaScript programs, when you need to know the call stack information, you can call Error.captureStackTrace() to achieve. In the past, if you need to know the call stack information, the general approach is to throw an Error object and capture it immediately, and obtain the call stack by accessing the stack property of the object. A simple example is as follows:

try {
   throw new Error();
} catch (e) {
   // e.stack contains stack data, which can be processed to ignore uninteresting stack information
}

Compared with this approach, it can be clearly seen that using Error.captureStackTrace() will be more concise, easy to use, and more elegant; and this may be the reason why Error.captureStackTrace() was added in V8.

Please log in to leave a comment.