Найти тему
Frontend Fusion Life!

Тайны Промисов или как правильно заказывать пиццу

Оглавление

Что такое промисы и зачем они нужны?

Промисы — это такие специальные объекты в JavaScript, которые помогают управлять асинхронными операциями. Представь себе, что ты заказал пиццу. Ты ведь не будешь стоять у двери и ждать её целый час, правда? Ты продолжишь заниматься своими делами, а когда пиццу привезут, курьер позвонит в дверь. Промисы работают примерно так же: они позволяют JavaScript продолжать выполнять код, пока выполняется асинхронная операция, а затем уведомляют, когда эта операция завершена.

Как это работает?

Промис может находиться в одном из трёх состояний:

  1. Pending (в ожидании): Начальное состояние, операция ещё не завершена.
  2. Fulfilled (выполнен): Операция успешно завершена.
  3. Rejected (отклонён): Операция завершена с ошибкой.

Создание промиса

Промис создается с помощью конструктора Promise, который принимает функцию с двумя параметрами: resolve и reject. Эта функция выполняет асинхронную операцию и вызывает resolve при успешном завершении или reject при ошибке.

Обработка результатов

Методы .then() и .catch() используются для обработки результатов промиса. Метод .then() принимает два аргумента: функцию для успешного завершения и функцию для обработки ошибок. Метод .catch() используется для обработки ошибок и часто размещается в конце цепочки.

Простой пример

Давай посмотрим на простой пример с промисом. Представь, что ты написал функцию, которая заказывает пиццу:

-2

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

Используй цепочки промисов

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

-3

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

-4

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

Всегда возвращай промис

Еще одна стандартная ошибка при работе с промисами, это забыть вернуть промис внутри then.

-5

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

-6

Вот так оно уже будет работать)

Не забывай про Promise.all Promise.race Promise.allSettled

Допустим, у нас есть массив с URL-адресами, по которым нужно отправить запросы и получить данные. Разработчик пытается использовать цикл for, чтобы обойти все промисы и получить результаты.

-7

Проблема здесь в том, что добавление данных в массив results происходит асинхронно, и поэтому после цикла результаты могут не быть доступны в ожидаемом порядке или вовсе не быть готовыми.

В качестве решения за вас уже все придумали. Просто используйте Promise.all или Promise.allSettled в зависимости от того нужно вам чтобы исполнились все запросы или нужно прекратить после первой же ошибки.

-8

В этом случае Promise.all() создаёт массив промисов, каждый из которых представляет асинхронный запрос. После того как все промисы завершатся (успешно или с ошибкой), мы получим массив с результатами запросов в том же порядке, в котором они были указаны в исходном массиве urls.

Использование Promise.all() помогает избежать проблемы асинхронного выполнения и гарантирует правильный порядок результатов.

Заключение

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

Так что вперед, используй промисы и делай свои приложения лучше! И если что-то пойдет не так, просто добавь .catch(). Удачи!

P.S

Здесь я намеренно не сказал ничего про async/await, который сильно упрощает жизнь, дабы дать понимание работы с чистыми промисами. Так же далеко не всегда мы имеем возможность работы с async/await, да и конструкция вида

Promise.all(promises)

читается приятнее чем.

async func()=>{
promises.forEach(promise=>{
await promise
})
}

Но вы всегда можете ознакомиться с материалом в другой моей статье.