Odtwarzanie problemu
Występuje problem podczas próby przekazywania komunikatów o błędach przy użyciu gniazd sieciowych. Mogę powtórzyć problem, z którym się spotykam, JSON.stringify
aby dotrzeć do szerszego grona odbiorców:
// node v0.10.15
> var error = new Error('simple error message');
undefined
> error
[Error: simple error message]
> Object.getOwnPropertyNames(error);
[ 'stack', 'arguments', 'type', 'message' ]
> JSON.stringify(error);
'{}'
Problem polega na tym, że kończę na pustym obiekcie.
Co próbowałem
Przeglądarki
Najpierw próbowałem opuścić node.js i uruchomić go w różnych przeglądarkach. Wersja Chrome 28 daje mi ten sam wynik i co ciekawe, Firefox przynajmniej próbuje, ale pomija komunikat:
>>> JSON.stringify(error); // Firebug, Firefox 23
{"fileName":"debug eval code","lineNumber":1,"stack":"@debug eval code:1\n"}
Funkcja zamiennika
Następnie spojrzałem na prototyp Error.prototype . Pokazuje, że prototyp zawiera metody takie jak toString i toSource . Wiedząc, że funkcji nie można sprecyzować, do wywołania JSON.stringify zawarłem funkcję zamiennika, aby usunąć wszystkie funkcje, ale potem zdałem sobie sprawę, że również zachowuje się dziwnie:
var error = new Error('simple error message');
JSON.stringify(error, function(key, value) {
console.log(key === ''); // true (?)
console.log(value === error); // true (?)
});
Wydaje się, że nie zapętla obiektu, jak zwykle, dlatego nie mogę sprawdzić, czy klucz jest funkcją i go zignorować.
Pytanie
Czy jest jakiś sposób na nawiasowanie natywnych komunikatów o błędach JSON.stringify
? Jeśli nie, dlaczego tak się dzieje?
Metody obejścia tego
- Trzymaj się prostych komunikatów o błędach opartych na łańcuchach lub twórz osobiste obiekty błędów i nie polegaj na rodzimym obiekcie Error.
- Właściwości ciągnięcia:
JSON.stringify({ message: error.message, stack: error.stack })
Aktualizacje
@Ray Toal Sugerowane w komentarzu, że patrzę na deskryptory właściwości . Teraz jest jasne, dlaczego to nie działa:
var error = new Error('simple error message');
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);
}
Wynik:
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: 'simple error message',
writable: true,
enumerable: false,
configurable: true }
Klucz: enumerable: false
.
Zaakceptowana odpowiedź stanowi obejście tego problemu.