Глобальная обработка ошибок в JavaScript

При написании кода на любом языке программирования никогда не получается обходиться без ошибок, даже если программа протестирована уже в сотый раз. И язык JavaScript тоже не исключение. Ошибки не перехваченные в коде программы, могут остановить выполнение остальных скриптов на странице. Но так как ошибка находится на стороне браузера пользователя, ее не получится увидеть, если не использовать специальных механизмов отслеживания клиентских ошибок и сохранения их на сервере.

Далее, мы рассмотрим пример установки глобального обработчика ошибок на странице, который будет отсылать информацию об ошибке на сервер.

Итак, код обработчика:


let hasLoggedOnce = false;

// Некоторые браузеры не сообщают номера строк и столбцов
// когда событие обрабатывается с помощью window.addEventListener('error', fn). Вот почему
// более надежным подходом является установка прослушивателя событий с помощью прямого назначения обработчика.
window.onerror = function (eventOrMessage, url, lineNumber, colNumber, error) {
    if (hasLoggedOnce || !eventOrMessage) {
        // Не имеет смысла сообщать об ошибке, если:
        // 1. уже сообщалось о другой ошибке - страница находится в недопустимом состоянии и может выдавать слишком много ошибок.
        // 2. предоставленная информация не имеет смысла (нет события или сообщения - браузер по какой-то причине не предоставил информацию).
        return;
    }

    hasLoggedOnce = true;
    if (typeof eventOrMessage !== 'string') {
        error = eventOrMessage.error;
        url = eventOrMessage.filename || eventOrMessage.fileName;
        lineNumber = eventOrMessage.lineno || eventOrMessage.lineNumber;
        colNumber = eventOrMessage.colno || eventOrMessage.columnNumber;
        eventOrMessage = eventOrMessage.message || eventOrMessage.name || error.message || error.name;
    }

    if (error && error.stack) {
        eventOrMessage = [eventOrMessage, '; Stack: ', error.stack, '.'].join('');
    }

    const jsFile = (/[^/]+.js/i.exec(url || '') || [])[0] || 'inlineScriptOrDynamicEvalCode';
    let stack = [eventOrMessage, 'Ошибка появилась ', jsFile, ':', lineNumber || '?', ':', colNumber || '?'].join('');

    // немного сокращаем сообщение, чтобы оно с большей вероятностью соответствовало ограничению длины URL-адреса браузера (которое в некоторых браузерах составляет 2083 символа).
    stack = stack.replace(/https?://[^/]+/gi, '');
    // вызов обработчика на стороне сервера, который, должен зарегистрировать ошибку в базе данных или файле журнала
    // заставляем браузер отправить информацию на сервер посредством загрузки изображения размером 1x1
    new Image().src = '/clientError?stack=' + encodeURIComponent(stack);

    // window.ENVIRONMENT_DEV - настраиваемое свойство, которому может быть присвоено значение true где-либо еще для целей отладки и тестирования
    if (window.ENVIRONMENT_DEV) {
        alert('Клиентская ошибка: ' + stack);
    }
}

Таким образом, мы создали обработчик клиентских ошибок и логирования их на сервер.

Источник