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

Итак, в этой лекции давайте поговорим о том, как обрабатывать ошибки в промисах. И для начала помните, что обещание, в котором происходит ошибка, является отклоненным обещанием.

Итак, в этой лекции мы узнаем, как обрабатывать отказы от промисов:

На самом деле единственный способ, которым обещание выборки отклоняется, — это когда пользователь теряет подключение к Интернету. Итак, на данный момент это будет единственная ошибка, которую мы здесь обработаем.

Теперь, чтобы имитировать потерю интернет-соединения, мы можем перейти сюда в Сеть, а затем мы можем изменить скорость здесь на Автономный режим. Однако, когда мы затем перезагрузим страницу, в основном все исчезнет, ​​и это не совсем то, что нам нужно. Мы хотим имитировать, что сначала страница все еще была загружена, но затем, когда пользователь выполняет запрос без Интернета, мы хотим увидеть, как происходит ошибка. Итак, давайте установим его обратно в Online, и теперь мы хотим, чтобы эта функция вызывалась только здесь всякий раз, когда пользователь нажимает кнопку. Таким образом, нам будет проще имитировать потерю интернет-соединения. Итак, здесь, в HTML, у нас уже есть кнопка, поэтому давайте закомментируем ее, а затем в сценарии, я думаю, здесь, так что мы уже выбрали ее здесь как эту кнопку. Итак, все, что мы будем делать сейчас, это щелкнуть btn.addEventListener, а затем здесь функция и так далее.

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

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

Теперь есть два способа обработки отклонений. Первый заключается в передаче второй функции обратного вызова в метод then. Таким образом, первая функция обратного вызова здесь всегда будет вызываться для выполнения обещания. так что для успешного. Но мы также можем передать второй обратный вызов, который будет вызван, когда обещание будет отклонено.

Итак, давайте сделаем это. И эта функция обратного вызова будет вызываться с аргументом, который по сути является самой ошибкой. Итак, давайте просто предупредим об ошибке. Хорошо, так что давайте попробуем это. И теперь у нас снова нет Интернета, поэтому нам сначала нужно сделать все нормально, поэтому загрузите страницу. Теперь теряем соединение и теперь делаем запрос. Итак, теперь мы фактически обработали ошибку, отобразив это окно с предупреждением. И ошибка, которую мы видели ранее здесь, теперь исчезла.

Итак, теперь у нас больше нет этой неперехваченной ошибки здесь, потому что мы на самом деле перехватили ошибку прямо здесь. Таким образом, обработка ошибки также называется отловом ошибки, и, опять же, это причина, по которой эта ошибка, которая у нас была раньше, исчезла. Итак, он сказал «Неперехваченная ошибка», но опять же, теперь мы на самом деле ловим ее здесь. Итак, теперь мы обрабатываем ошибку, которая может возникнуть в этом промисе, хорошо.

Теперь в этом случае больше нет ошибок, потому что в основном цепочка останавливается здесь, когда эта ошибка возникает и когда она обрабатывается прямо здесь. Но что, если на самом деле в этом обещании fetch не было ошибки? Итак, что, если это обещание выборки действительно было выполнено, но второе здесь было отклонено.

Ну тогда нам тоже пришлось бы ловить здесь ошибку. Таким образом, мы должны были бы прийти сюда, получить эту функцию и вставить ее сюда, а также обработать ошибку прямо здесь.

Однако это немного раздражает, поэтому на самом деле существует лучший способ обработки всех этих ошибок в глобальном масштабе только в одном централизованном месте. Поэтому вместо всех этих функций обратного вызова давайте просто их удалим. хорошо. Так что гораздо лучше иметь один обратный вызов в then, а потом вместо этого мы можем обрабатывать все ошибки, независимо от того, где они появляются в цепочке, прямо в конце цепочки, добавляя метод catch.

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

Хорошо, давайте теперь попробуем это снова, и нам придется вернуть Интернет, перезагрузить страницу, вернуться в автономный режим. И действительно, теперь мы получаем ту же ошибку, то же окно предупреждения, что и раньше. Теперь вместо того, чтобы иметь это раздражающее окно с предупреждением, давайте просто заблокируем сообщение об ошибке в консоли и создадим здесь некоторую строку.

Итак, ошибка, а затем давайте просто добавим несколько смайликов, чтобы мы точно знали, какие ошибки были напечатаны нами самими. Что ж, давайте добавим сюда пару из них. И на самом деле, мы также можем стилизовать это с помощью console.error. Помните, кажется, я показывал вам это в какой-то момент в начале курса. Но в любом случае, в реальном приложении с реальным пользовательским интерфейсом обычно просто выводить ошибку на консоль недостаточно. Итак, вместо того, чтобы просто выводить что-то в консоль, давайте также отобразим сообщение об ошибке, которое может увидеть пользователь. Итак, это более реальный вариант использования этого блока catch. Итак, я добавляю здесь новый блок, поэтому мы все еще хотим, конечно, заблокировать ошибку в консоли, но кроме этого давайте теперь создадим функцию, которая также будет отображать какую-то ошибку, хорошо. Итак, давайте сделаем это снаружи, и я назову это renderError.

Итак, это функция, и она может принять сообщение, просто назовите ее так. И точно так же, как элементы страны, мы хотим прикрепить это к странамКонтейнеру, а затем вставить.adjacent. И на этот раз не HTML, а вставку соседнего текста. Так что это новый, но в основном он делает то же самое, что и insertAdjacent HTML, но просто с текстом, поэтому он не создает никаких новых элементов HTML. Хорошо. Кроме того, помните, что мы всегда возвращали непрозрачность к единице. Так же, как мы делали раньше в функции рендеринга стран, потому что иначе этот контейнер даже не будет виден. И на самом деле давайте поместим эту функцию в самый верх файла вместе с функцией рендеринга страны. Вот так вот. Итак, снова в обоих случаях, чтобы действительно увидеть контейнер, мы устанавливаем непрозрачность на единицу. Хорошо. И так теперь вот давайте воспользуемся этим рендером, так что не страна конечно Error, допустим что-то пошло не так. Тогда здесь мы снова можем использовать наши смайлики, почему бы и нет? И затем здесь давайте снова напечатаем ошибку, и на самом деле эта ошибка, которая генерируется здесь, является реальным объектом JavaScript.

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

Теперь, чтобы попробовать это, нам нужно снова подключиться к сети, а затем в автономном режиме, проверить консоль. И действительно, здесь мы получаем нашу пользовательскую ошибку, видимую смайликами, а затем наше собственное сообщение для пользователя.

Теперь это не очень красиво, но это не главное, и, как вы видите, это просто error.msg. В то время как здесь у нас есть вся ошибка. Таким образом, это включает в себя TypeError и даже эту так называемую трассировку стека, поэтому она точно показывает нам, откуда исходит ошибка. Итак, вот как мы обрабатываем ошибки, возникающие в промисах в любом обработчике then. Таким образом, в основном обрабатывается любой отказ от обещания, независимо от того, где это происходит в цепочке.

Теперь, чтобы закончить, есть еще один быстрый метод, который я хочу вам показать, и который также доступен для всех промисов. Таким образом, кроме then и catch есть еще метод finally. Итак, давайте добавим здесь, наконец, наконец. И тогда функция обратного вызова, которую мы определили здесь, всегда будет вызываться, что бы ни случилось с промисом. Поэтому независимо от того, выполнено ли обещание или отклонено, эта функция обратного вызова, которую мы определяем здесь, будет вызываться всегда. Так что в этом разница между двумя другими, так что метод then вызывается только тогда, когда обещание выполнено, а этот вызывается только тогда, когда обещание отклонено. Теперь метод finally не всегда полезен, но иногда это действительно так. Поэтому мы используем этот метод для чего-то, что всегда должно произойти, независимо от результата обещания.

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

Итак, в основном эта часть здесь всегда происходит, несмотря ни на что, верно? Так что неважно, рендерим ли мы страну в случае успеха или рендерим ли мы ошибку в случае ошибки, независимо от того, что нам всегда нужно делать это. Итак, давайте уберем это отсюда, так что я скопирую это сюда и деактивирую это в обоих случаях, а затем давайте поместим это сюда, в обработчик finally, хорошо. И теперь нам больше не нужен Offline, так что давайте просто перезагрузим, поместим его сюда, и да, это прекрасно работает.

Просто обратите внимание, что это на самом деле работает, потому что сам catch также возвращает промис. Так что это единственный способ, почему это здесь может работать, поэтому, конечно, это работает только с обещаниями. Итак, да, опять же, это может работать только в том случае, если сам catch также возвращает обещание.

Хорошо, теперь давайте попробуем смоделировать другую ошибку, чтобы я мог показать вам, что нам нужно делать дальше. Допустим, мы пытаемся найти страну, которой просто не существует. И так, или API не найдет для этого никакого результата.

Скажем так, так что давайте посмотрим. И мы получаем эту странную ошибку, что мы не можем прочитать флаг свойства undefined в строке 152. Итак, в основном это происходит из этого места, но, конечно, затем в трассировке стека мы можем видеть, откуда именно это происходит, так что это происходит из getCountryData . Что ж, в данном случае это не очень полезно, но иногда проверка этой трассировки стека может быть действительно полезной. Так или иначе, эта ошибка странная и на самом деле не отражает истинной ошибки, которая заключается в том, что наш API не может найти ни одну страну с таким названием. Таким образом, истинная ошибка, конечно, не в том, что мы не можем прочитать флаг неопределенности, а в том, что наш API не может найти ни одну страну. И это отражено здесь с кодом состояния 404.

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

В данном случае мы действительно хотим сообщить пользователю, что страна с таким названием не найдена. Именно этим мы и займемся в следующей лекции, чтобы эта не стала слишком длинной.