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

Это важная для понимания концепция, которая лежит в основе других концепций асинхронного JS, таких как async / await.

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

Чтобы понять это, мы должны четко понимать одну вещь.

Любое значение, возвращаемое обработчиками обещаний, будет упаковано как обещание.

Это означает, что если мы вернем значение из обработчика обещания, например - then, catch или finally, оно будет заключено в оболочку как обещание.

Попробуем на примере. Попробуйте написать приведенный ниже фрагмент кода в консоли.

Попробуйте зарегистрировать переменную secondObject в консоли, чтобы проверить ее тип. Вы получите следующий результат

Из этого примера ясно, что secondObject не является числом, а фактически является обещанием, повторяя нашу предыдущую точку зрения:

Любое значение, возвращаемое обработчиками обещаний, будет упаковано как обещание.

Тогда как нам использовать обещание, возвращенное обработчиком? Простой. Как и любые другие обещания - с then/catch/finally обработчиками.

Итак, если мы хотим получить значение 2 из предыдущего примера, применим другой обработчик then к обещанию secondObject или еще лучше, просто добавьте новый обработчик then к предыдущему обработчику then, как показано ниже.

Теперь будет напечатано 2.

Этот процесс объединения нескольких обещаний называется цепочкой обещаний.

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

Давайте посмотрим на реальный пример.

Представьте, что вы создаете приложение для социальных сетей, в котором пользователи могут создавать сообщения, добавлять к нему комментарии. Вроде как Facebook. Но не токсичен: D. Как пользователь с правами администратора вы хотите видеть всех пользователей в системе и все сообщения первого пользователя на вашей панели управления.

Вы должны сделать 2 действия подряд:

  1. Получить всех пользователей
  2. Получить все сообщения, связанные с первым пользователем

Мы будем использовать fetch API для выполнения HTTP-запросов, и мы будем использовать https://jsonplaceholder.typicode.com/ в качестве поставщика API для этого примера.

Чтобы получить всех пользователей, мы можем использовать приведенный ниже код

Довольно нормальные вещи. Мы передаем URL-адрес для получения списка пользователей методу fetch. fetch выполняет сетевой вызов и возвращает обещание, к которому мы обращаемся с помощью обработчика then.

Но обратите внимание, как здесь мы используем цепочку обещаний.
Это потому, что ответ от fetch API будет иметь тип Response.
Чтобы извлечь содержимое тела JSON из ответа, мы используем метод .json(), который возвращает обещание, оборачивая тело JSON. Таким образом, наш массив users будет доступен во втором обработчике then.

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

Аналогично предыдущему коду. Единственная разница заключается в использовании неявного возврата в стрелочных функциях.

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

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

Обработка ошибок

Что если что-то пойдет не так? Как вы обрабатываете ошибки в цепочке обещаний?

Напомним, во 2-й части этой серии мы уже затронули этот вопрос. Пойдите, проверьте это, если вы еще не сделали.

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

В цепочке обещаний, если ошибка возникает в блоке then, ее можно обработать в обработчике ошибок следующего then блока или следующего catch блока. Но что выбрать? Это зависит от ответа на вопрос

Должна ли ошибка нарушить всю цепочку обещаний?

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

Давайте посмотрим, как в действии

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

Мы не обработали ошибку, поэтому после ее появления then обработчики не выполняются.

Теперь давайте разберемся с ошибкой.

Обработка ошибок, НЕ разрывая цепочку обещаний

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

Мы добавляем функцию (строка № 7) для обработки случая ошибки для 2-го then (строка № 3) в цепочке.

Если вы заметили, ошибка не обрабатывается в непосредственном блоке then. Это означает, что если ошибка возникает в цепочке обещаний (в нашем случае при выборке пользователей), ошибка будет распространяться по цепочке до тех пор, пока не достигнет функции обработки ошибок (если есть), которая затем будет выполнена и возобновится нормальное выполнение цепочки.

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

Обработка ошибок путем разрыва цепочки обещаний

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

Здесь мы используем блок catch в конце цепочки для обработки любой ошибки в цепочке обещаний.

Выполните код, и вы увидите, что цепочка разорвалась, когда произошла ошибка.

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

Если вы нашли эту статью полезной, не забудьте аплодировать и поделиться ею с друзьями. Если у вас есть предложения / комментарии, дайте мне знать. Обязательно следуйте за мной, поскольку мы будем развивать это, разбираясь в различных методах обещания Promise.any (), Promise.all (), а также async / ждать.