Автор оригинала: FreeCodeCamp Community Member.
Позвольте мне начать с того, что я понял – JavaScript – отличный язык, а не винить. Я был полностью виноват – моя умственная модель обращения с ошибками была неполной, и это вызвало проблему. Следовательно, этот пост.
Но сначала позвольте мне дать вам какой-то контекст. Я писал кучу кода с участием сторонних API ( повторяющиеся счеты на стрипею и API на подписку и подписки , чтобы быть конкретным) и написал класс Wrapper и некоторые поперечные обработчики сервера, чтобы ответить на запросы от интерфейсной сети приложение. Все приложение реагирует + типографский + узел, с помощью KOA Server Отказ
Как часть этого я пытался справиться с следующими ошибками:
- Ошибки, брошенные по API полосой
- Ошибки, брошенные моим классом оболочки, особенно при выборе пользовательских данных из базы данных
- Ошибки в обработчиках маршрутов, которые возникают из комбинации вышеуказанного.
Во время разработки мои самые распространенные ошибки были неполными данными в запросах серверов и неправильные данные, переданные на полоску.
Чтобы помочь вам визуализировать поток данных, позвольте мне дать вам немного фона на стороне сервера. Как правило, это какова цепочка вызовов функций:
Обработчик маршрута -> Slipe Wrapper -> Plipe API
Первая функция, называемая функцией, будет в обработчике маршрута, затем в классе полосных обертков, внутри которого будет называться метод API полосы. Таким образом, стек вызовов имеет обработчик маршрута внизу (сначала называемая функциями) и методом API полосы на верхней части (последняя называемая функция).
Проблема заключалась в том, что я не понял, где поставить мою обработку ошибок. Если я не поставил обработчик ошибок в сервере, то узел будет сбоя (буквально, выйти за выполнение!), И передний конец будет принимать ошибку HTTP-ответ (как правило, HTTP 5xx ERR0R ). Поэтому я положил несколько попробовать
Художественные обработчики внутри различных методов называются и добавлены операторы ведения журнала внутри поймать
блокировать. Таким образом, я мог отладить ошибку, отслеживая журналы.
Пример вызовов логики:
function stripeAPI(arg){ console.log('this is the first function') if(!arg) throw new Error('no arg!') // else saveToDb() } function stripeWrapper(){ console.log('this is the second function, about to call the first function') try{ stripeAPI() } catch(err) { // console.log(' this error will not bubble up to the first function that triggered the function calls!') } } function routeHandler(){ console.log('this is the third function, about to call the second function') stripeWrapper() } function callAll(){ try{ routeHandler() return 'done' } catch (err){ console.log('error in callAll():', err) return ' not done ' } } callAll()
Проблемы?
- Если я не регистрировал ошибку, я потерял Ошибка! В приведенном выше фрагменте обратите внимание, что, хотя я позвонил
Сначала ()
Без необходимых аргументов ошибка определена в определенииПервый
не бросил! Кроме того, нетsavetodb ()
Метод определен … И все же это не было поймано! Если вы запускаете этот код выше, вы увидите, что он возвращает «Готово» – и вы понятия не имеете, что ваша база данных не обновлена, и что-то пошло не так! ☠️☠️☠️. - Моя консоль имела слишком много журналов, повторяя ту же ошибку. Это также означало, что в производстве было чрезмерное ведение журнала …?
- Код выглядел уродливым. Почти как уродливая как моя консоль.
- Другие, которые работали с кодом, обнаружили, что он запутал и отладки кошмара. ?
Ни один из них не являются хорошими результатами, и все избегают.
Концепции
Итак, давайте сделаем некоторые основы с пути. Я уверен, что вы знаете их, но некоторые люди не могут, и давайте не оставим их позади!
Некоторые основные терминологии:
Ошибка . – Также известен как «исключение», является когда что-то выходит не так в узлевом коде, и программа выходит сразу. Ошибки, если не обрабатываются, приведет к тому, что программа будет прийти к визжению, а уродливые сообщения извержены в консоль, с длинным и в целом отвратительным сообщением об ошибках.
Бросить – бросить
Оператор – это то, как язык обрабатывает ошибку. Используя бросить
Вы генерируете исключение, используя значение, которое вы поставили после оператора. Обратите внимание, что код после бросить
не выполняется – в этом смысле это как Возвращение
утверждение.
Ошибка . – Есть JavaScript объект называется Ошибка
. Отказ Ошибка получает «брошенное», чтобы помочь программисту знать, что что-то нужно обрабатывать. Подумайте об этом как о маленькой тикающей бомбе? которые бросаются из одной функции к другой внутри цепочки функционных вызовов. Технически, вы можете бросить любые данные, включая JavaScript примитивы как ошибку, но, как правило, хорошая идея бросить Ошибка
. объект.
Вы обычно строите Ошибка
. Объект, проходя в строке сообщения, как так: Новая ошибка («Это ошибка»)
Отказ Но просто создавая новый Ошибка
. ? Объект бесполезно, так как это только половина работы. Вы дошли до бросить
Это так может быть поймано. Вот как это становится полезным.
Языки, как правило, поставляются с Стандартный набор ошибок, Но вы можете создать пользовательское сообщение об ошибке с Новая ошибка («Это мое сообщение об ошибке»)
Конструктор, и ваше сообщение об ошибке должно помочь вам поработать, что происходит. Больше на Ошибки узла.
Поймать – Это то, что вы делаете, когда кто-то бросает что-то у вас, верно? Вы, вероятно, сделаете это рефлексивно, даже если кто-то бросил вас одним из них …?!
поймать
Заявление в JavaScript позволяет обрабатывать ошибку? Это бросается. Если вы не поймаете ошибку, то ошибка «пузыри вверх» (или вниз, в зависимости от того, как вы просматриваете стек вызова) до тех пор, пока он не достигнет первой под названием функцию, и там она будет сбиваться программа.
В моем примере моим ошибка, выброшенная на полосою API, позволит встать на свой путь к функции обрабатываемого маршрута, если только я не поймаю его где-то по пути и справился с ним. Если я не справимся с ошибкой, узел бросит uncuptexception
Ошибка, а затем завершайте программу.
Вернемся к моему примеру:
Стек вызовов
Обработчик маршрута -> Slipe Wrapper -> Plipe API
Путь ошибок
Slipe API ( ? выбрасывает здесь) -> API обертка ( � � не поймал) -> Маршрут Обработчик ( � �still не поймал) -> Ccrrahhh ???
Мы хотим избегать сбоев приложений, поскольку он может привести к повреждению ваших данных, ваше состояние быть непоследовательным, и ваш пользователь, чтобы подумать, что ваше приложение отстой. Таким образом, обработка ошибок, вдумчиво требует много уровней анализа.
Есть некоторые подробные руководства по обращению об ошибках в JavaScript, а одно из моих любимых – здесь , но я приведу итоги своих ключевых наклон для вас здесь.
Try-catch
Используйте их для изящных ошибок, но будьте осторожны о где и Когда Отказ Когда ошибки пойманы и не обрабатываются правильно, они потеряны. Это процесс «пузыринга» происходит только до тех пор, пока ошибка не сталкивается с поймать
утверждение. Если есть поймать
Заявление в цепочке вызовов, которая перехватывает ошибку, ошибка не будет разорвать приложение, но не обрабатывать ошибку, будет скрывать его! Затем он проходит как аргумент для поймать
И это требует от вас, чтобы справиться с этим там.
try{ // code logic } catch (error) { // handle the error appropriately }
Так что очень важно поймать и Обращайтесь с ошибкой в точке, где она делает наиболее логичный смысл для вас, когда вы должны отладить его. Заманчиво думать, что вы должны поймать его в самом первом месте (последняя функция вызывала, которая сидит прямо на верхней части стека вызовов), но это не так!
Маршрут-Обработчик -> Уплотнитель на полоску (не поймай здесь!) -> API полоса
Если я поставил свой попробовать
В полосой обертке, которая напрямую призывает API полос, то у меня нет информации о где Моя функция обертки нашивки была вызвана. Может быть, это был обработчик, может быть, это был еще один метод внутри моей обертки, может быть, это было в другом файле всего! В этом простом примере это, очевидно, называется обработчиком маршрута, но в приложении Real World его можно назвать в нескольких местах.
Вместо этого мне имеет смысл поставить попробовать
В обработчике маршрута, который является самым первым местом, где начинаются вызовы функций, которые привели к ошибке. Таким образом, вы можете проследить стек вызовов (также называемым раскручиванием стека вызовов) и сверните в ошибку. Если я отправлю плохие данные на полоску, она бросит ошибку, и эта ошибка пройдет через мой код, пока не поймаю его.
Но когда я поймаю его, мне нужно обращаться с этим правильно, или я мог непреднамеренно скрыть эту ошибку. Обработка ошибок обычно означает решение, нужен ли мне мой передний пользователь, чтобы знать, что что-то пошло не так (например, их платеж не работал, например), или это просто внутренняя ошибка сервера (например, полоса не может найти идентификатор продукта I ID Прошло), что мне нужно изящно обрабатывать, не отключая моих передних конечных пользователей и разбиваем код узла. Если я добавил вещи в базу данных, которые не являются правильными, то я должен очистить эти ложные пишеты сейчас.
При обращении с ошибкой, это хорошая идея для входа в систему, чтобы я мог отслеживать приложение для ошибок и сбоев в производстве и эффективно отладки. Итак, на самом случае, по крайней мере, обработка будет включать в себя регистрацию ошибки в поймать
утверждение. Но…
function stripeAPI(arg){ console.log('this is the first function') if(!arg) throw new Error('no arg!') // else saveToDb() } function stripeWrapper(){ console.log('this is the second function, about to call the first function') try { stripeAPI() } catch(err) { console.log('Oops! err will not bubble up to the first function that triggered the function calls!') } } function routeHandler(){ console.log('this is the third function, about to call the second function') stripeWrapper() } function callAll(){ try { routeHandler() return 'done' } catch (err){ console.log('error in callAll():', err) return ' not done ' } } callAll()
… Как вы можете видеть выше, если я поймаю его и ловит его на среднем уровне (мой класс для обертки), он не достигнет Routehenler
или Callall
И мое приложение не узнает что-то пошло не так. Callall
все еще возвращается сделано
И единственным доказательством чего-то пошло не так, было в операторе журнала: «Упс! ERR не будет пузым до первой функции, которая вызвала вызовы функций!
Отказ Если бы мы не ставили оператор журнала там, что ошибка исчезла без следа.
Это «скрытие ошибок», и она делает отладку боли. Если я добавлю попробовать
Но ничего не делай в поймать
Заявление, я помешаю мою программу разбивающейся. Но я также в конечном итоге «скрываю» проблему! Обычно он приводит к непоследовательному состоянию – части моего сервера считают, что все в порядке, и говорит мой передний конец. Но другая часть моего сервера указала, что что-то не так!
В этом простом примере их легко разгадать, но думать о глубоком вложенном, вызванном всем вашим приложением – какой кошмар!
Если вам абсолютно необходимо обрабатывать ошибку в середине стека вызовов, то обязательно перекатите ошибку соответствующим образом. Это означает, что закончится ваш поймать
Заявление с другим Ошибка броска
операция. Таким образом, ошибка будет выброшена снова и продолжать «пузыми» к первой функции (внизу стека вызовов), которая вызвала цепочку вызовов, где она может быть правильно обработана снова.
Вот что похоже, добавляя только один маленький перебрасывающий в stripewrapper ()
функция. Запустите код и увидим разницу в результате, потому что Callall ()
Теперь передается ошибка!
function stripeWrapper(){ console.log('this is the second function, about to call the first function') try{ stripeAPI() } catch(err) { console.log('Oops! err will not bubble up to to first function that triggered the function calls!') throw err // add this to re-throw! } } function callAll(){ try{ routeHandler() return 'done' } catch (err){ // catches the re-thrown error and prints it to console! console.log('error in callAll():', err) return ' not done ' } }
Поскольку вы бросили ошибку на средней сцене, она пошла на внешнюю границу и там попала. Код возвращается не сделано
И вы можете исследовать, почему ошибка говорит «нет arg». Вы также можете увидеть, что он никогда не выполняется savetodb ()
, поскольку ошибка бросила, прежде чем этот код может быть выполнен! Это может быть хорошо в тех случаях, когда вы экономите вещи в базу данных Предполагая, что не было никаких ошибок до этого момента Отказ Представьте себе сохранение вещей в базу данных, которые никогда не должны быть сохранены – это грязные данные в базе данных сейчас! ???
Итак, не делайте то, что я делал в моих первых днях программирования и просто зарегистрируйте ошибку в каждый Шаг в стеке вызов и переверните его. Это просто означает, что вы получите несколько журналов для каждой ошибки, так как проходит через стек вызовов! Перехватить только ошибку в месте, где вы можете наиболее эффективно и использовать его, в идеале один раз в данной цепочке вызовов.
В общем, это действительно помогает, если вы разместите свой Попробуйте поймать
Заявление на внешней (первой вызывающей) функции, которая лежит в нижней части стека вызовов. Вы можете идентифицировать это как место, что ошибка будет пузыми до Незадолго до бросать uncuptexception
ошибка. Это хорошее место, чтобы поймать, журнал и справиться с этим.
Чтобы увидеть разницу в обработке, когда вы не используете попробовать
Просто модифицируйте Callall ()
выглядеть так:
function callAll(){ routeHandler() // this won't run! console.log('This function is not contained inside a try-catch, so will crash the node program.') } callAll()
Вы заметите, что console.log
Заявление никогда не работает здесь, потому что программа вылетает, когда RouteHandler ()
заканчивается выполнением.
Эмпирические правила ???
Итак, давайте суммируем некоторые быстрые правила, которые будут охватывать 90 +% ваших потребностей:
- Не помешайте свой код с помощью
попробовать
заявления - Попробуйте как можно больше к
поймать
только один раз в данной цепочке вызовов функций - Попробуйте разместить это
поймать
На самой внешней границе – первая функция, которая запускает цепочку вызовов функций (внизу стека вызовов) - Не оставляйте свой
поймать
Заявление пустое как способ остановить вашу программу от аварии! Если вы не обрабатываете его, шансы это приведет к непоследовательному состоянию между вашим передним и концом спины. Это может быть опасно и привести к ужасному пользователю?! - Не используйте
поймать
Заявление только в середине стека вызовов, а не на внешней границе. Это заставит ошибку получить «скрытую» в середине вашего кода, где она не собирается правильно помочь вам отладки или управлять данными. Другие, которые работают с вашим кодом, найдут где вы живете и отрезаете интернет-соединение. - Поймайте его там, где вам нужно знать, и где вы можете значимы, делать все, что нужно почистить вещи.
Slipe API ( ? выброшены здесь) -> Обелочка API ( ? Прохождение) -> Обработчик маршрута ( ? поймал, обрабатывался, вошли в систему) -> ???
Спасибо за чтение!
Если вы хотели бы узнать больше о моем путешествии в код, проверить Эпизод 53 из FreeCodecamp подкаст , где Quincy (основатель FreeCodeCamp) и я делюсь нашим опытом в качестве карьерных чейнджеров, которые могут помочь вам в вашем путешествии. Вы также можете получить доступ к подкасте на iTunes , Сказки и Spotify Отказ
Я также буду держать несколько AMAS и вебинаров в ближайшие месяцы. Если это интересно вам, пожалуйста, дайте мне знать, собираясь здесь Отказ И, конечно, вы также можете твитнуть меня на @Zubinpratap Отказ