javascript - Was ist die tatsächliche Ausgabe von console.log(error) und wie bekomme ich genau dieselbe Ausgabe als Zeichenkette?
In einem Node.js-Projekt, das Typescript verwendet und auf ES2020 abzielt, benutze ich eine benutzerdefinierte Fehlerklasse wie folgt:
class InvalidParamsError extends Error {
}
try {
throw new InvalidParamsError();
} catch (error) {
if (error instanceof Error) {
console.log(error);
console.log(error.message); // Different output
console.log(error.stack); // Different output
console.log(error.toString()); // Different output
}
}
Die Ausgabe, die ich in der Konsole erhalte, ist:
InvalidParamsError
at REPL11:2:13
at ...
Error
at REPL11:2:13
at ...
Error
undefined
Wie kann ich genau dasselbe Ergebnis als Zeichenkette erhalten, ohne es in der Konsole ausgeben zu müssen?
error.message, error.stack und error.toString() geben alle unterschiedliche Strings zurück, und keiner von ihnen zeigt InvalidParamsError als Teil der Ausgabe, stattdessen wird ein generischer Error angezeigt. Ich weiß, dass ich das manuell beheben könnte, indem ich den name des InvalidParamsError im Konstruktor setze, aber selbst dann kann ich nicht genau die gleiche Ausgabe wie console.log(error) als String erhalten.
Ich habe versucht, den Quellcode der Node.js-Konsole anzusehen, konnte aber keine Antwort finden.
Ich ziele auf ES2020 ab, also denke ich nicht, dass dies mit früheren TypeScript-Problemen beim Erweitern von eingebauten Objekten wie Error zusammenhängt.
Antwort #1
Ich habe versucht, den Quellcode der Node.js-Konsole anzusehen, konnte aber keine Antwort finden.
In node.js verwendet console.log util.format, das wiederum auf util.inspect zurückgreift. Der Code dieser Funktion geht durch einige Umwege, ruft aber letztendlich die Funktion formatError auf, die die Ausgabe erzeugt, die Sie suchen.
Insbesondere der Teil über die Verwendung des Namens InvalidParamsError erfolgt in improveStack, wo er den Standard-error.name, mit dem der error.stack beginnt, durch das Standard-Präfix der Objektdarstellung (z. B. Array(n) oder Object) ersetzt, das aus getConstructorName und getPrefix erstellt wird.
Wie kann ich genau diese Ausgabe als Zeichenkette erhalten, ohne sie auf der Konsole ausgeben zu müssen?
import { inspect } from 'node:util';
class InvalidParamsError extends Error {}
try {
throw new InvalidParamsError();
} catch (error) {
const string = inspect(error);
…
}
Antwort #2
Wonach Sie suchen, ist das format-Hilfsprogramm, das die console-Stdout-Methoden verwenden. Zusätzlich können Sie den Konstruktor erweitern, um dieselben Argumente wie die Elternklasse zu übernehmen. Sie können bei Bedarf weitere angeben:
import { format } from 'node:util';
class InvalidParamsError extends Error {
constructor(...params: Parameters<typeof Error>) {
super(...params);
this.name = 'InvalidParamsError';
}
}
function thisFunctionThrows() {
let outputString = '';
try {
// intellisense for constructor args!
throw new InvalidParamsError('message', { cause: 'error cause' });
} catch (error: unknown) {
if (error instanceof Error) {
outputString = format(error);
}
}
return outputString;
}
const errorString = thisFunctionThrows();
console.log(errorString);
einen Namen zur Funktion hinzugefügt, um sicherzustellen, dass der Trace korrekt ist
