Reproduktion des Problems
Ich stoße auf ein Problem, wenn ich versuche, Fehlermeldungen über Websockets weiterzugeben. Ich kann das Problem, dem ich gegenüberstehe, mittels JSON.stringify
reproduzieren, um eine breitere Zielgruppe anzusprechen:
// node v0.10.15
> var error = new Error('einfache Fehlermeldung');
undefined
> error
[Error: einfache Fehlermeldung]
> Object.getOwnPropertyNames(error);
[ 'stack', 'arguments', 'type', 'message' ]
> JSON.stringify(error);
'{}'
Das Problem ist, dass ich am Ende ein leeres Objekt erhalte.
Was ich versucht habe
Browser
Zuerst habe ich node.js verlassen und es in verschiedenen Browsern ausgeführt. Chrome-Version 28 liefert mir das gleiche Ergebnis, und interessanterweise macht Firefox zumindest einen Versuch, aber ließ die Nachricht aus:
>>> JSON.stringify(error); // Firebug, Firefox 23
{"fileName":"debug eval code","lineNumber":1,"stack":"@debug eval code:1\n"}
Replacer-Funktion
Dann habe ich mir das Error.prototype angesehen. Es zeigt, dass das Prototyp Methoden wie toString und toSource enthält. Da Funktionen nicht in Strings umgewandelt werden können, habe ich eine Replacer-Funktion beim Aufrufen von JSON.stringify eingefügt, um alle Funktionen zu entfernen, bemerkte aber dann, dass auch dies ein seltsames Verhalten zeigte:
var error = new Error('einfache Fehlermeldung');
JSON.stringify(error, function(key, value) {
console.log(key === ''); // true (?)
console.log(value === error); // true (?)
});
Es scheint nicht über das Objekt zu iterieren wie es normalerweise tun würde, und daher kann ich nicht überprüfen, ob der Schlüssel eine Funktion ist und ihn ignorieren.
Die Frage
Gibt es einen Weg, nativ Error-Meldungen mit JSON.stringify
zu stringifizieren? Wenn nicht, warum tritt dieses Verhalten auf?
Wege, um dieses Problem zu umgehen
- Bei einfachen stringbasierten Fehlermeldungen bleiben oder persönliche Fehlerobjekte erstellen und nicht auf das native Error-Objekt verlassen.
- Eigenschaften abrufen:
JSON.stringify({ message: error.message, stack: error.stack })
Updates
@Ray Toal schlug in einem Kommentar vor, dass ich mir die Eigenschaftsdeskriptoren anschaue. Es ist jetzt klar, warum es nicht funktioniert:
var error = new Error('einfache Fehlermeldung');
var propertyNames = Object.getOwnPropertyNames(error);
var descriptor;
for (var property, i = 0, len = propertyNames.length; i < len; ++i) {
property = propertyNames[i];
descriptor = Object.getOwnPropertyDescriptor(error, property);
console.log(property, descriptor);
}
Ausgabe:
stack { get: [Function],
set: [Function],
enumerable: false,
configurable: true }
arguments { value: undefined,
writable: true,
enumerable: false,
configurable: true }
type { value: undefined,
writable: true,
enumerable: false,
configurable: true }
message { value: 'einfache Fehlermeldung',
writable: true,
enumerable: false,
configurable: true }
Schlüssel: enumerable: false
.
Die akzeptierte Antwort bietet eine Lösung für dieses Problem.