Каковы лучшие практики обработки ошибок JavaScript?

137

Я ищу , чтобы начать делать свою JavaScript немного больше ошибок доказательства, и я нахожу много документации по использованию try, catch, finallyи throw, но я не найти тонну советов от экспертов о том, когда и куда бросать ошибки.

  • Должен ли каждый фрагмент кода быть заключен в try / catch?
  • Есть ли еще такой совет о том, в какой момент следует обнаруживать ошибки?
  • Есть ли недостатки в том, чтобы выдавать ошибки вместо тихого сбоя кода в производственной среде?
  • Это было затронуто в SO до реализации, но есть ли эффективная стратегия регистрации ошибок JS сервера?
  • Что еще мне следует знать об ошибках перехвата в моем приложении?

Я также полностью заинтересован в том, чтобы слушать книги, в которых есть отличные главы или подробные объяснения обработки ошибок. Красноречивый JavaScript затрагивает этот вопрос, но не слишком предписывающий или категоричный по этому поводу.

Спасибо за любой совет, который вы можете дать!

Джошуа Коди
источник
Это, безусловно, зависит от того, насколько сильно вы потерпите неудачу, если что-то пойдет не так, и от количества возможных сообщений об ошибках. Вы же не хотите потерпеть неудачу, потому что ваш каталог регистрации ошибок теперь заполнен, не так ли? - Вы вообще сюда смотрели? stackoverflow.com/search?q=error+logging+javascript
mplungjan
@mplungjan - я просмотрел там ответы, но не многие из них казались каноническими, а поиски лучших практик обработки ошибок / исключений Javascript ничего не дали, поэтому я подумал, что было бы полезно попытаться получить некоторые сжатые мысли, как для моих собственное понимание и будущие искатели. Возможно, это та тема, в которой невозможно прописать передовой опыт, но каждая ситуация в высшей степени уникальна?
Джошуа Коди
1
"Должен ли каждый фрагмент кода быть заключен в попытку / уловку?" Конечно нет. Есть много кода, который, как вы знаете, всегда будет работать (при условии, конечно, что вы его протестируете, но цель try / catch не в том, чтобы уловить или замазать ошибки кодирования). Оборачивайте только код, который иногда может дать сбой из-за чего-то вне его контроля, обычно таких вещей, как доступ к ресурсам и т. Д. Примечание: некоторые вещи, которые могут выйти из строя, имеют встроенную обработку ошибок, например, я бы не стал кодировать Ajax с нуля, когда существует множество библиотек, которые справляются с кроссбраузерными проблемами и позволяют указать функцию обработчика ошибок.
nnnnnn
1
Это хороший вопрос, Джош, +1. Есть много синтаксических советов, но, как вы говорите, это простая часть. Это затрагивается в ответе на этот вопрос ( stackoverflow.com/questions/2825427/… ), где объясняется, что исключения не так часто используются в JS, и приводятся причины.
Whitneyland 06

Ответы:

63

Чрезвычайно интересный набор слайдов по обработке ошибок Enterprise JavaScript можно найти по адресу http://www.devhands.com/2008/10/javascript-error-handling-and-general-best-practices/

Вкратце он резюмирует:

  1. Предположим, ваш код не сработает
  2. Регистрировать ошибки на сервере
  3. Вы, а не браузер, обрабатываете ошибки
  4. Определите, где могут возникнуть ошибки
  5. Кидайте собственные ошибки
  6. Различать фатальные и нефатальные ошибки
  7. Обеспечьте режим отладки

Слайды содержат гораздо больше деталей и, скорее всего, дадут вам какое-то направление.

ОБНОВИТЬ

Вышеупомянутую презентацию можно найти здесь: http://www.slideshare.net/nzakas/enterprise-javascript-error-handling-presentation

cdmdotnet
источник
24
Ссылка на devhands не работает.
Райан Гейтс,
7
Тем, кто прочитал это в 2017 году, я бы сказал, что вы не получите особой пользы от слайдов - это резюме дает вам 90% информации. Это все еще ценная информация. Ура!
Филипп Эбер
29

Николас Закас из Yahoo! fame выступил с докладом об обработке ошибок предприятия ( слайды ) на Ajax Experience 2008, в котором предложил что-то вроде этого:

function log(sev,msg) {
    var img = new Image();
    img.src = "log.php?sev=" +
        encodeURIComponent(sev) +
        "&msg=" + encodeURIComponent(msg);
}

// usage
log(1, "Something bad happened.")

// Auto-log uncaught JS errors
window.onerror = function(msg, url, line) {
    log(1, msg);
    return true;
}

Год спустя Николас Закас опубликовал в своем блоге обновление, в котором был включен умный шаблон для автоматического внедрения кода обработки ошибок в вашу производственную среду (с использованием аспектно-ориентированного программирования).

Когда вы начнете регистрировать вызовы window.error, вы заметите две вещи:

  1. Если ваш сайт довольно сложный, вы регистрируете много ошибок.
  2. Вы увидите кучу бесполезных сообщений "window.error в undefined: 0"

Уменьшить поток записей журнала так же просто, как проверить серьезность и / или случайное число перед входом на сервер:

function log(sev,msg) {
    if (Math.random() > 0.1) return; // only log some errors

    var img = new Image();
    img.src = "log.php?sev=" +
        encodeURIComponent(sev) +
        "&msg=" + encodeURIComponent(msg);
}

Обработка бесполезных ошибок «window.error in undefined: 0» зависит от архитектуры вашего сайта, но вы можете попытаться идентифицировать все вызовы Ajax и генерировать исключение, когда что-то не удается (возможно, возвращая трассировку стека с помощью stacktrace.js ).

Йенс Роланд
источник
67
Я знаю, что это старый вопрос, но предлагать случайным образом игнорировать некоторые ошибки - одна из худших идей, которые я когда-либо слышал.
jbabey 01
26
@jbabey: Для небольшого сайта вы правы, но если у вас большой сайт с 100 000 или миллионами пользователей, вам действительно не нужно наводнять свои серверы (или Интернет) избыточными запросами на ведение журнала. В достаточно большой системе каждая реальная ошибка будет происходить десятки тысяч раз в день, поэтому такая форма ограничения работает отлично. Идея фактически реализована в Facebook.
Йенс Роланд,
1
Регистрация ошибок в режиме отладки, вероятно, так же важна, как и ограничение отчетов об ошибках в производстве, поэтому можно отметить, что необходимо решение для управления этим значением, ограничивающим порог регистрации.
frattaro 02
2
@NickBull Я перепроектировал кучу модулей JavaScript для Facebook еще в 2011-2012 годах; вот где я это нашел.
Йенс Роланд
1
@NickBull только что проверил мои старые файлы, они еще остались. Я нашел этот трюк в модуле загрузчика Facebook: if (global.logJSError) if (Math.random() < .01) logJSError('bootloader', {(по общему признанию, этот код ограничивает не все ошибки, а только определенный класс ошибок тайм-аута)
Йенс Роланд
7

IHMO, вы должны использовать обработку ошибок в javascript, как и на нескольких других языках (AFAIK: Python, Java).

Для лучшей читаемости (и, возможно, лучшей производительности, хотя я не уверен, что это действительно сильно повлияет), вам следует использовать блок try / catch в основном в следующих случаях:

  • Часть кода, которую вы хотите обернуть, является ключевой частью всего алгоритма . В случае неудачи он может:

    • создавать ошибки в следующей части кода (например, из-за отсутствия переменной ...)
    • заставить страницу выглядеть не так, как ожидалось (влияние на контент или CSS)
    • сделать результаты странными для пользователя (влияние на поведение кода)
  • Вы знаете, что код, который вы пишете, совместим не со всеми браузерами.

  • Вы планировали, что код может выйти из строя (потому что нет другого способа проверить, что он должен работать с помощью блоков if ... then ...)
  • А также, если вы хотите отладить, не беспокоя конечного пользователя

В конце концов, у экспертов по javascript могут быть и другие элементы.

мои 2 цента в коробку,

С Уважением,

Максимум

JMax
источник
1
«Часть кода, которую вы хотите обернуть, является ключевой частью всего алгоритма» - может зависеть от того, как вы хотите справиться с ошибкой. Если вы знаете, что нет возможности продолжить работу с алгоритмом после сбоя, может быть лучше обернуть все это в try / catch, потому что, если ваш try / catch (например) похоронен внутри вложенных циклов, это будет большим ударом по производительности , С другой стороны, если вы можете предпринять какие-либо действия при исключении и продолжить работу с алгоритмом, вам понадобится более детальная настройка try / catch.
nnnnnn
5

В дополнение к другим ответам: одна важная вещь - использовать контекстные данные, доступные в объектах ошибок JavaScript и в window.onerrorпараметрах функции.

Такие вещи, как stacktrace (errorObject.stack), имя файла, номер строки и номер столбца. Обратите внимание, что у каждого браузера есть некоторые отличия ... так что постарайтесь получить хорошие ошибки.

Могут быть проблемы даже с самим объектом консоли . Я использую настраиваемую функцию window.onerror, вдохновленную этим, и специальную функцию для отслеживания любого заданного стандартного объекта ошибки, вдохновленного этим кодом .

Еще один хороший момент - включить версию вашего веб-приложения где-нибудь рядом с трассировкой стека (для быстрого и безопасного копирования и вставки). Вы также можете более агрессивно отображать ошибки (предупреждение ...) в режиме разработки, так как разработчики не будут постоянно следить за консолью браузера и могут не видеть некоторые проблемы.

Также используйте, избегайте использования throw 'My message', используйте throw new Error('My message'), вы даже можете иметь собственные ошибки, прочтите эту статью .

Всегда добавляйте некоторый контекст к ошибкам (версия, идентификатор объекта, какое-то настраиваемое сообщение, ...), а также убедитесь, что вы проводите различие между внешними ошибками (некоторые внешние данные или обстоятельства привели к сбою вашей системы) и внутренними ошибками / assertions (ваша собственная система испортилась), прочтите о « Дизайн по контракту ».

Вот руководство .

Также подумайте об использовании общей обработки ошибок, такой как перехватчики ваших библиотек и фреймворков:

Кристоф Русси
источник