Повторные попытки HTTP-запросов в Angular.

Angular

Доступ к данным из бэкенда — основа почти каждого одностраничного приложения. Весь динамический контент загружается с сервера.

В большинстве случаев HTTP-запросы работают хорошо и возвращают желаемый результат. Но, бывает, запрос выполняется неверно.

Представьте: кто-то использует ваш веб-сайт через точку доступа в поезде, едущем со скоростью 200 км/ч. 🚅 Да, скорость сети может быть низкой, но HTTP-запрос все еще возвращает желаемый результат.

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

Обновление влияет на текущее состояние приложения. Пользователь может, например, потерять данные, которые ввел в форму.

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

Повторение неудачных запросов

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

В Angular мы создаем сервис и внедряем HttpClient, чтобы получить данные из бэкенда.

Здесь ничего особенного. Мы внедряем HTTPClient и выполняем простой запрос get . Если этот запрос вернет ошибку, мы обработаем ее и вернем пустой Observable, чтобы продолжить выполнение.

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

Но как нам повторить запрос, если конечная точка приветствия не доступна или возвращает ошибку? Может, у RxJS есть оператор? Конечно, есть. У RxJS есть операторы на все случаи жизни. 😉

Первая вещь, которая приходит в голову — оператор retry. Давайте посмотрим на его определение.

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

Звучит как нужный нам оператор. Давайте включим его в нашу цепочку.

Мы успешно применили оператор retry. Давайте проверим, как он влияет на поведение HTTP-запроса внутри приложения-примера.

Приложение супер простое — оно просто выполняет HTTP-вызов, когда мы нажимаем на кнопку «вызвать сервер».

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

Прекрасно! Повторили.🤘

Но есть что улучшить. Обратите внимание, что повторы выполняются немедленно, что не особо пригодится в нашем примере с тоннелем.🤔

Отложенные повторные попытки

Мы не выезжаем из тоннеля сразу же после въезда в него — мы проводим там некоторое время. Следовательно, нам нужно растянуть период повтора, откладывая каждую попытку.

Нам нужен более тонкий контроль над поведением повторов, чтобы решать, когда повторы должны выполняться. Тут оператора retry недостаточно. Давайте снова обратимся к документам RxJs.

Кажется, операторretryWhen подойдет. Вот определение из официальных документов:

Возвращает Observable, отражающий исходный Observable c исключением, возникшим из-за ошибки. Если Observable вызывает ошибку, этот метод вызывает Throwable, который провоцирует ошибку Observable, возвращенного из notifier . Если Observable вызывает complete или error, тогда метод вызывает complete илиerrorдочерней подписки. В противном случае, этот метод повторно подпишется на исходный Observable.

Что? 😶Звучит очень сложно. Попробую объяснить проще.

Оператор retryWhenпринимает обратный вызов, который возвращает Observable. Возвращенный Observable определяет поведение оператораretryWhen, основываясь на следующих правилах:

Оператор retryWhen:

— повторяет исходный Observable, если возвращенный Observable успешно эмитится;

— завершается и выдает ошибку, когда возвращенный Observable выдает ошибку;

— завершается, если возвращенный Observable завершается.

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

Специально для сайта ITWORLD.UZ. Новость взята с сайта NOP::Nuances of programming