Riproduzione del problema
Sto riscontrando un problema quando provo a trasmettere messaggi di errore utilizzando i socket Web. Posso replicare il problema che sto affrontando utilizzando JSON.stringify
per soddisfare un pubblico più ampio:
// 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);
'{}'
Il problema è che finisco con un oggetto vuoto.
Quello che ho provato
browser
Per prima cosa ho provato a lasciare node.js ed eseguirlo in vari browser. La versione 28 di Chrome mi dà lo stesso risultato e, cosa abbastanza interessante, almeno un tentativo di Firefox ha lasciato fuori il messaggio:
>>> JSON.stringify(error); // Firebug, Firefox 23
{"fileName":"debug eval code","lineNumber":1,"stack":"@debug eval code:1\n"}
Funzione di sostituzione
Ho quindi esaminato il Error.prototype . Mostra che il prototipo contiene metodi come toString e toSource . Sapendo che non è possibile restringere le funzioni, ho incluso una funzione di sostituzione quando ho chiamato JSON.stringify per rimuovere tutte le funzioni, ma poi ho capito che anche questo aveva un comportamento strano:
var error = new Error('simple error message');
JSON.stringify(error, function(key, value) {
console.log(key === ''); // true (?)
console.log(value === error); // true (?)
});
Non sembra passare sopra l'oggetto come farebbe normalmente, e quindi non posso controllare se il tasto è una funzione e ignorarlo.
La domanda
Esiste un modo per stringere i messaggi di errore nativi con JSON.stringify
? In caso contrario, perché si verifica questo comportamento?
Metodi per aggirare questo
- Attenersi a semplici messaggi di errore basati su stringhe o creare oggetti di errore personali e non fare affidamento sull'oggetto Error nativo.
- Proprietà pull:
JSON.stringify({ message: error.message, stack: error.stack })
aggiornamenti
@Ray Toal Suggerito in un commento che do un'occhiata ai descrittori di proprietà . Ora è chiaro perché non funziona:
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);
}
Produzione:
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 }
Legenda: enumerable: false
.
La risposta accettata fornisce una soluzione alternativa per questo problema.