Каков наилучший способ перехвата ВСЕХ исключений, возникающих в JavaScript?
Очевидно, что лучший способ - это попробовать ... поймать. Но с асинхронными обратными вызовами и т. д. Это может быть сложно.
Я знаю, что браузеры IE и Gecko поддерживают window.onerror, но как насчет Opera и Safari?
Вот несколько тестовых примеров, для которых я хотел бы иметь центральное решение для обработки исключений:
// ErrorHandler-Test1
var test = null;
test.arg = 5;
// ErrorHandler-Test2
throw (new Error("Hello"));
// ErrorHandler-Test3
throw "Hello again";
// ErrorHandler-Test4
throw {
myMessage: "stuff",
customProperty: 5,
anArray: [1, 2, 3]
};
// ErrorHandler-Test5
try {
var test2 = null;
test2.arg = 5;
} catch(e) {
ErrorHandler.handleError(e);
}
// ErrorHandler-Test6
try {
throw (new Error("Goodbye"));
} catch(e) {
ErrorHandler.handleError(e);
}
// ErrorHandler-Test7
try {
throw "Goodbye again";
} catch(e) {
ErrorHandler.handleError(e);
}
// ErrorHandler-Test8
try {
throw {
myMessage: "stuff",
customProperty: 5,
anArray: [1, 2, 3]
};
} catch(e) {
ErrorHandler.handleError(e);
}
Если вы думаете о каких-либо других тестовых примерах, укажите их. В некоторых из этих случаев упоминается метод ErrorHandler.handleError. Это всего лишь рекомендуемый совет при использовании try ... catch.
В WebKit отсутствие window.onerror было проблемой с 2003 г., но похоже, что это наконец решается. Конечно, Opera останется упрямой.
FYI window.onerror отлично работает в - Firefox 7.0.1 - IE 8 - Chrome 16 - Opera 11.60
Не уверен, почему это было закрыто. Проголосовал за возобновление работы.
Согласен, это полезный вопрос. Единственное, о чем я могу думать, - это то, что casperOne боялся, что вместо этого это превратится в какую-то дискуссию о войне браузеров?
Вероятно, это было закрыто из-за того, как оно было оформлено. В частности, «Что такое техника Лучший для ...». Это можно рассматривать как аргумент, и поэтому вопрос закрыт как неконструктивный. Попробуйте переформулировать его без таких модификаторов, как «лучший». Почему бы просто не спросить: «Как мне перехватить все исключения JS?»



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


WebKit (Safari, Chrome и т. д.) Теперь, похоже, поддерживает onerror.
Исходное сообщение: Насколько мне известно, WebKit / Safari не поддерживает событие onerror. Это чертовски досадно.
Нет, это не так. На вопрос: «а как же Opera и Safari?»
То есть, я специально ответил на вопрос, заданный в вопроснике.
Я думаю, он имел в виду «что [мне делать] с Opera и Safari [у которых нет window.onerror]?»
@nickf, может быть, но если это так, это очень плохо сформулировано, и моя интерпретация в худшем случае понятна и в лучшем случае наиболее вероятна. Это довольно плохая причина для людей голосовать против моего ответа, особенно с учетом того, что вопрос несостояние it, и другие читатели могут извлечь выгоду из утвердительного или отрицательного утверждения.
Кажется, теперь Chrome поддерживает это.
Если вы используете такую библиотеку, как jQuery, для назначения всех ваших обработчиков событий, вы можете использовать комбинацию window.onerror и обертывания кода обработчика событий jQuery и функции готовности с функцией обработки ошибок (см. Отслеживание ошибок JavaScript: почему window.onerror недостаточно).
window.onerror: перехватывает все ошибки в IE (и большинство ошибок в Firefox), но ничего не делает в Safari и Opera.Я уже читал статью, которая не предлагает никакого решения. Я не использую jQuery, но меня беспокоит, о чем вы говорите. Вы хотите сказать, что jQuery ест исключения ?! Или они просто предоставляют функцию ведения журнала (что полезно только после ответа на мой исходный вопрос)?
jQuery не делает ничего особенного с Исключениями. Но если вы используете jQuery для добавления всех своих событий, это дает вам единое место для добавления оператора try catch и кода обработки ошибок, как описано во второй ссылке в моем ответе.
Предоставленная ссылка переместилась: blogs.cozi.com/tech/2008/04/…
Это все еще правда? Я просто попробовал обычный подход к работе с onerror в Safari + Chrome и, похоже, работает правильно.
Ссылка, которую вы дали о том, почему «этого недостаточно», является довольно старой информацией, и сейчас это не так.
На самом деле подход jquery не так уж и плох. Видеть:
http://docs.jquery.com/Events/error#fn
и:
$(window).error(function(msg, url, line){
$.post("js_error_log.php", { msg: msg, url: url, line: line });
});
для тех, кто обнаруживает это сейчас - jquery на самом деле рекомендует не привязывать событие к событию window.error - см. ссылку на документацию выше. Извлечение: обработчик события ошибки jQuery не должен быть прикреплен к объекту окна. [...] Вместо этого используйте window.onerror.
конечно, это не должно быть привязано таким образом, это нелогично! к тому времени, когда это предложение было сделано (даже если оно было успешно выполнено ...), может произойти много ошибок.
try-catch - не всегда лучшее решение. Например, в Chrome 7.0 вы теряете красивую трассировку стека в окне консоли. Повторное отображение исключения не помогает. Я не знаю ни одного решения, которое сохраняет следы стека и, позволяя вам реагировать на исключение.
Поймайте все исключения своим собственным обработчиком исключений и используйте instanceof.
$("inuput").live({
click : function (event) {
try {
if (somethingGoesWrong) {
throw new MyException();
}
} catch (Exception) {
new MyExceptionHandler(Exception);
}
}
});
function MyExceptionHandler(Exception) {
if (Exception instanceof TypeError ||
Exception instanceof ReferenceError ||
Exception instanceof RangeError ||
Exception instanceof SyntaxError ||
Exception instanceof URIError ) {
throw Exception; // native error
} else {
// handle exception
}
}
MyExcetpionHandler выдаст собственную ошибку, поскольку нет блока try-catch.
Посетите http://www.nczonline.net/blog/2009/03/10/the-art-of-throwing-javascript-errors-part-2/
Я также искал обработку ошибок, трассировку стека и регистрацию действий пользователя, это то, что я нашел, надеюсь, что это также поможет вам https://github.com/jefferyto/glitchjs
Немного поработав, можно получить достаточно полные трассировки стека во всех браузерах.
Современные Chrome и Opera (то есть все, что основано на движке рендеринга Blink) полностью поддерживают черновую спецификацию HTML 5 для ErrorEvent и window.onerror. В обоих этих браузерах вы можете использовать window.onerror или (что удивительно!) Правильно привязать к событию error:
// Only Chrome & Opera pass the error object.
window.onerror = function (message, file, line, col, error) {
console.info(message, "from", error.stack);
// You can send data to your server
// sendData(data);
};
// Only Chrome & Opera have an error attribute on the event.
window.addEventListener("error", function (e) {
console.info(e.error.message, "from", e.error.stack);
// You can send data to your server
// sendData(data);
})
К сожалению, Firefox, Safari и IE все еще существуют, и мы тоже должны их поддерживать. Поскольку stacktrace недоступен в window.onerror, нам нужно проделать немного больше работы.
Оказывается, единственное, что мы можем сделать, чтобы получить трассировку стека ошибок, - это обернуть весь наш код в блок try{ }catch(e){ }, а затем посмотреть на e.stack. Мы можем несколько упростить этот процесс с помощью функции под названием wrap, которая принимает функцию и возвращает новую функцию с хорошей обработкой ошибок.
function wrap(func) {
// Ensure we only wrap the function once.
if (!func._wrapped) {
func._wrapped = function () {
try{
func.apply(this, arguments);
} catch(e) {
console.info(e.message, "from", e.stack);
// You can send data to your server
// sendData(data);
throw e;
}
}
}
return func._wrapped;
};
Это работает. Любая функция, которую вы переносите вручную, будет хорошо обрабатывать ошибки.
Вы можете отправить данные с помощью тега изображения следующим образом
function sendData(data) {
var img = newImage(),
src = http://yourserver.com/jserror + '&data=' + encodeURIComponent(JSON.stringify(data));
img.crossOrigin = 'anonymous';
img.onload = function success() {
console.info('success', data);
};
img.onerror = img.onabort = function failure() {
console.error('failure', data);
};
img.src = src;
}
Однако вам нужно сделать бэкэнд для сбора данных и внешний интерфейс для визуализации данных.
В Ататус мы работаем над решением этой проблемы. Atatus обеспечивает не только отслеживание ошибок, но и реальный мониторинг пользователей.
Give a try https://www.atatus.com/
Отказ от ответственности: я веб-разработчик в Atatus.
Это правда, что в современных браузерах перехват window.onerror для ошибок, которые всплывают наверх, вместе с добавлением обработчиков событий jQuery для ошибок Ajax, перехватит практически все объекты Error, добавленные в код вашего клиента. Если вы вручную настраиваете обработчик для window.onerror, в современных браузерах это делается с помощью window.addEventListener('error', callback),
в то время как в IE8 / 9 вам нужно вызвать
window.attachEvent('onerror', callback).
Обратите внимание, что затем вам следует рассмотреть среду, в которой обрабатываются эти ошибки, и причину этого. Одно дело - поймать как можно больше ошибок с их трассировками стека, но появление современных инструментов разработки F12 решает этот вариант использования при локальной реализации и отладке. Точки останова и т. д. Предоставят вам больше данных, чем доступно из обработчиков, особенно для ошибок, вызванных сторонними библиотеками, которые были загружены из запросов CORS. Вам необходимо предпринять дополнительные шаги, чтобы указать браузеру предоставить эти данные.
Ключевой проблемой является предоставление этих данных в производственной среде, так как ваши пользователи гарантированно будут запускать гораздо более широкий спектр браузеров и версий, чем вы можете протестировать, и ваш сайт / приложение неожиданно сломается, независимо от того, сколько QA вы бросите. Это.
Чтобы справиться с этим, вам нужен трекер производственных ошибок, который улавливает каждую ошибку, возникшую в браузерах вашего пользователя, когда они используют ваш код, и отправляет их в конечную точку, где вы можете просматривать данные и использовать их для исправления ошибок по мере их появления. . В Raygun (отказ от ответственности: я работаю в Raygun) мы приложили кучу усилий, чтобы обеспечить отличный опыт для этого, поскольку есть много подводных камней и проблем, которые следует учитывать при наивной реализации.
Например, есть вероятность, что вы объедините и уменьшите свои ресурсы JS, что означает, что ошибки, возникшие из минифицированного кода, будут иметь следы нежелательного стека с искаженными именами переменных. Для этого вам понадобится инструмент сборки для создания исходных карт (мы рекомендуем UglifyJS2 для этой части конвейера) и ваш трекер ошибок, чтобы принимать и обрабатывать их, превращая искаженные трассировки стека обратно в удобочитаемые. Raygun делает все это из коробки и включает конечную точку API для приема исходных карт в том виде, в каком они создаются в процессе сборки. Это ключевой момент, поскольку они не должны быть общедоступными, иначе любой может уничтожить ваш код, отрицая его цель.
Клиентская библиотека raygun4js также поставляется с window.onerror как для современных, так и для устаревших браузеров, а также с готовыми хуками jQuery, поэтому для настройки вам нужно только добавить:
<script type = "text/javascript" src = "//cdn.raygun.io/raygun4js/raygun.min.js" </script>
<script>
Raygun.init('yourApiKey').attach();
</script>
Также имеется множество встроенных функций, включая возможность изменять полезную нагрузку ошибки перед ее отправкой, добавлять теги и пользовательские данные, метаданные о пользователе, который увидел ошибку. Это также облегчает получение хороших трассировок стека из вышеупомянутых сторонних сценариев CORS, которые решают ужасную «ошибку сценария» (которая не содержит сообщений об ошибках и трассировки стека).
Более важная проблема заключается в том, что из-за огромной аудитории в Интернете ваш сайт будет генерировать тысячи повторяющихся экземпляров каждой ошибки. Служба отслеживания ошибок, такая как Лучевая пушка, умеет объединять их в группы ошибок, чтобы вы не утонули в потоке уведомлений, и позволяет вам видеть каждую фактическую ошибку, готовую к исправлению.
Просто потому, что ясно, что вы не заметили комментариев к моему ответу: кажется, вы проголосовали против меня за «изложенное в вопросе», когда оно читается как вопрос: «а как насчет Opera и Safari?» Я специально ответил на поставленный здесь вопрос. Какого черта?