Reproduciendo el problema
Me encuentro con un problema al intentar pasar mensajes de error usando los sockets web. Puedo replicar el problema que estoy usando JSON.stringify
para atender a un público más amplio:
// 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);
'{}'
El problema es que termino con un objeto vacío.
Lo que he intentado
Navegadores
Primero intenté dejar node.js y ejecutarlo en varios navegadores. La versión 28 de Chrome me da el mismo resultado y, curiosamente, Firefox por lo menos hace un intento pero dejó el mensaje:
>>> JSON.stringify(error); // Firebug, Firefox 23
{"fileName":"debug eval code","lineNumber":1,"stack":"@debug eval code:1\n"}
Función de reemplazo
Luego miré el prototipo Error.prototype . Muestra que el prototipo contiene métodos como toString y toSource . Sabiendo que las funciones no pueden ser encadenadas, incluí una función de reemplazo al llamar a JSON.stringify para eliminar todas las funciones, pero luego me di cuenta de que también tenía un comportamiento extraño:
var error = new Error('simple error message');
JSON.stringify(error, function(key, value) {
console.log(key === ''); // true (?)
console.log(value === error); // true (?)
});
No parece recorrer el objeto como lo haría normalmente, y por lo tanto no puedo verificar si la tecla es una función e ignorarla.
La pregunta
¿Hay alguna forma de stringificar mensajes de error nativos con JSON.stringify
? Si no, ¿por qué ocurre este comportamiento?
Métodos para evitar esto
- Quédese con mensajes de error simples basados en cadenas, o cree objetos de error personales y no confíe en el objeto de error nativo.
- Propiedades de extracción:
JSON.stringify({ message: error.message, stack: error.stack })
Actualizaciones
@ Ray Toal Sugerido en un comentario que eche un vistazo a los descriptores de propiedades . Ahora está claro por qué no funciona:
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);
}
Salida:
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 }
Clave: enumerable: false
.
La respuesta aceptada proporciona una solución para este problema.