Обработка исключений JavaScript - PullRequest
81 голосов
/ 15 октября 2008

Как лучше всего перехватывать ВСЕ исключения, возникающие в JavaScript?

Очевидно, что лучшая техника - использовать try ... catch. Но с асинхронными обратными вызовами и так далее, это может быть сложно.

Я знаю, что браузеры 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.

Ответы [ 8 ]

23 голосов
/ 15 октября 2008

Если вы используете библиотеку наподобие jQuery для назначения всех ваших обработчиков событий, вы можете использовать комбинацию window.onerror и упаковывать код обработчика событий jQuery и функцию ready с функцией обработки ошибок (см. : Отслеживание ошибок JavaScript: почему window.onerror недостаточно ).

  • window.onerror: отлавливает все ошибки в IE (и большинство ошибок в Firefox), но ничего не делает в Safari и Opera.
  • Обработчики событий jQuery: отлавливает ошибки событий jQuery во всех браузерах.
  • Функция jQuery ready: отлавливает ошибки инициализации во всех браузерах.
22 голосов
/ 15 октября 2008

WebKit (Safari, Chrome и т. Д.) Теперь поддерживает onerror.

Оригинальный пост: Насколько я знаю, WebKit / Safari не поддерживает событие onerror. Это чертовски стыдно.

7 голосов
/ 23 января 2009

На самом деле, подход 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 });
});
6 голосов
/ 08 ноября 2012

Перехватывайте все исключения с помощью собственного обработчика исключений и используйте 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/

4 голосов
/ 07 декабря 2010

try-catch не всегда лучшее решение. Например, в Chrome 7.0 вы теряете хорошую трассировку стека в окне консоли. Отмена исключения не помогает. Я не знаю ни одного решения, которое бы сохраняло следы стека и , позволяющие вам реагировать на исключения.

2 голосов
/ 31 июля 2015

Немного поработав, можно получить трассировки стека, которые достаточно полны во всех браузерах.

Современные 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.log(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.log(e.error.message, "from", e.error.stack);
    // You can send data to your server
    // sendData(data);
})

К сожалению, Firefox, Safari и IE все еще существуют, и мы также должны их поддерживать. Поскольку трассировка стека недоступна в 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.log(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.log('success', data);
    };
    img.onerror = img.onabort = function failure() {
        console.error('failure', data);
    };
    img.src = src;
}

Однако вы должны сделать бэкэнд для сбора данных и интерфейс для визуализации данных.

В Ататус мы работаем над решением этой проблемы. Atatus обеспечивает не только отслеживание ошибок, но и мониторинг реальных пользователей.

Дай попробовать https://www.atatus.com/

Отказ от ответственности: я веб-разработчик в Atatus.

1 голос
/ 18 сентября 2015

Это правда, что в современных браузерах перехват окон 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, которые решают страшную «ошибку скрипта» (которая не содержит сообщений об ошибках и трассировки стека).

Более важной проблемой является то, что из-за огромной аудитории в Интернете ваш сайт будет генерировать тысячи повторяющихся экземпляров каждой ошибки. Служба отслеживания ошибок, такая как Raygun , имеет умения сворачивать их в группы ошибок, чтобы вы не утонули в потоке уведомлений, и позволяет видеть каждую фактическую ошибку, готовую к исправлению.

0 голосов
/ 03 июня 2013

Я также искал обработку ошибок, отслеживание стека и ведение журнала действий пользователя. Это то, что я нашел, надеюсь, это также поможет вам https://github.com/jefferyto/glitchjs

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...