Воспроизведение проблемы
У меня возникает проблема при попытке передать сообщения об ошибках с помощью веб-сокетов. Я могу воспроизвести проблему, с которой я столкнулся, используя 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"}
Функция Replacer
Затем я просмотрел 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.
- Свойства Pull:
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
.
Принятый ответ обеспечивает обходной путь для этой проблемы.