Reproduzindo o problema
Estou com um problema ao tentar passar mensagens de erro usando soquetes da web. Posso replicar o problema que estou enfrentando JSON.stringify
para atender a um público mais amplo:
// 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);
'{}'
O problema é que eu acabo com um objeto vazio.
O que eu tentei
Navegadores
Tentei sair do node.js e executá-lo em vários navegadores. A versão 28 do Chrome me dá o mesmo resultado e, curiosamente, o Firefox pelo menos tenta, mas deixa de fora a mensagem:
>>> JSON.stringify(error); // Firebug, Firefox 23
{"fileName":"debug eval code","lineNumber":1,"stack":"@debug eval code:1\n"}
Função substituidora
Então olhei para o erro.protótipo . Isso mostra que o protótipo contém métodos como toString e toSource . Sabendo que as funções não podem ser restringidas, incluí uma função substituta ao chamar JSON.stringify para remover todas as funções, mas depois percebi que ela também tinha um comportamento estranho:
var error = new Error('simple error message');
JSON.stringify(error, function(key, value) {
console.log(key === ''); // true (?)
console.log(value === error); // true (?)
});
Parece não fazer um loop sobre o objeto como faria normalmente e, portanto, não posso verificar se a chave é uma função e ignorá-la.
A questão
Existe alguma maneira de restringir mensagens de erro nativas com JSON.stringify
? Caso contrário, por que esse comportamento ocorre?
Métodos para contornar isso
- Atenha-se a mensagens de erro simples baseadas em string ou crie objetos de erro pessoais e não confie no objeto Error nativo.
- Propriedades de extração:
JSON.stringify({ message: error.message, stack: error.stack })
Atualizações
@Ray Toal Sugerido em um comentário que dê uma olhada nos descritores de propriedades . Agora está claro por que não 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);
}
Resultado:
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 }
Key: enumerable: false
.
A resposta aceita fornece uma solução alternativa para esse problema.