Воспроизведение проблемы
Я столкнулся с проблемой при попытке передать сообщения об ошибках с помощью веб-сокетов. Я могу повторить проблему, с которой сталкиваюсь, JSON.stringify
чтобы удовлетворить более широкую аудиторию:
// 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);
'{}'
Проблема в том, что я получаю пустой объект.
Что я пробовал
Браузеры
Сначала я попытался покинуть node.js и запустить его в разных браузерах. Chrome версии 28 дает мне тот же результат, и, что интересно, Firefox по крайней мере делает попытку, но пропускает сообщение:
>>> JSON.stringify(error); // Firebug, Firefox 23
{"fileName":"debug eval code","lineNumber":1,"stack":"@debug eval code:1\n"}
Функция заменителя
Затем я посмотрел на Error.prototype . Это показывает, что прототип содержит такие методы, как toString и toSource . Зная, что функции не могут быть строковыми, я включил функцию- заменитель при вызове JSON.stringify, чтобы удалить все функции, но затем понял, что у него тоже странное поведение:
var error = new Error('simple error message');
JSON.stringify(error, function(key, value) {
console.log(key === ''); // true (?)
console.log(value === error); // true (?)
});
Кажется, он не зацикливается на объекте, как обычно, и поэтому я не могу проверить, является ли ключ функцией, и игнорировать его.
Вопрос
Есть ли способ привести в порядок собственные сообщения об ошибках JSON.stringify
? Если нет, то почему это происходит?
Методы обойти это
- Придерживайтесь простых сообщений об ошибках на основе строк или создавайте личные объекты ошибок и не полагайтесь на собственный объект Error.
- Тянуть свойства:
JSON.stringify({ message: error.message, stack: error.stack })
Обновления
@Ray Toal Предложено в комментарии, что я смотрю на дескрипторы свойств . Теперь понятно, почему это не работает:
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);
}
Вывод:
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 }
Ключ: enumerable: false
.
Принятый ответ обеспечивает обходной путь для этой проблемы.