Введение
JavaScript Promises могут быть сложными для понимания. Поэтому я хотел бы записать то, как я понимаю промисы.
Понимание промисов
Промис вкратце:
“Представь, что ты ребенок. Твоя мама обещает тебе, что на следующей неделе купит тебе новый телефон.”
Ты не знаешь, получите ли вы этот телефон до следующей недели. Твоя мама может действительно купить тебе новый телефон, или не купить.
Это и есть обещание. Обещание имеет три состояния. Они таковы:
- Pending: Ты не знаешь, получите ли вы этот телефон
- Fulfilled: Мама довольна, она покупает тебе новый телефон
- Rejected: Мама недовольна, она не покупает тебе телефон
Создание промиса
Давайте превратим это в JavaScript.
Код достаточно выразителен сам по себе.
Вот как обычно выглядит синтаксис промиса:
Использование промисов
Теперь, когда у нас есть промис, давайте воспользуемся им:
Давайте запустим пример и посмотрим результат!
Демо: https://jsbin.com/nifocu/1/edit?js,console
Цепочка промисов
Промисы могут быть цепочкой.
Представьте, что вы, ребенок, обещаете своему другу, что покажете ему новый телефон, когда мама купит вам его.
Это еще одно обещание. Давайте запишем это!
Примечания: Мы можем сократить приведенный выше код, написав его следующим образом:
Давайте свяжем промисы. Вы, ребенок, можете начать промис showOff
только после промиса willIGetNewPhone
.
Вот как можно связать промисы.
Промисы асинхронны
Промисы асинхронны. Давайте выведем сообщение до и после вызова промиса.
Каков ожидаемый порядок вывода? Возможно, вы ожидаете:
1. before asking Mom
2. Hey friend, I have a new black Samsung phone.
3. after asking mom
Однако фактический порядок вывода следующий:
1. before asking Mom
2. after asking mom
3. Hey friend, I have a new black Samsung phone.
Вы не перестанете играть, ожидая обещания мамы (нового телефона). Это то, что мы называем асинхронностью: код будет выполняться без блокировки или ожидания результата. Всё, что нужно ждать завершения промиса, помещается в .then
.
Вот полный пример на ES5:
Promises в ES5, ES6/2015, ES7/Next
ES5 – Большинство браузеров
Демо-код работает в средах ES5 (все основные браузеры + NodeJs), если включить библиотеку Bluebird для promise. Это потому, что ES5 не поддерживает promise из коробки. Другая известная библиотека promise – Q от Kris Kowal.
ES6 / ES2015 – Современные браузеры, NodeJs v6
Демо-код работает сразу после установки, так как ES6 нативно поддерживает промисы. Кроме того, с функциями ES6 мы можем упростить код с помощью стрелочной функции и использовать const
и let
.
Вот полный пример на ES6:
Обратите внимание, что все var
заменены на const
. Все function(resolve, reject)
упрощены до (resolve, reject) =>
. Эти изменения дают несколько преимуществ.
ES7 – Async/Await
ES7 ввел синтаксис async
и await
. Он упрощает асинхронный синтаксис, делая его более понятным без использования .then
и .catch
.
Перепишем наш пример с использованием синтаксиса ES7:
Обещания и когда их использовать
Зачем нам нужны обещания? Как выглядел мир до появления обещаний? Прежде чем отвечать на эти вопросы, давайте вернемся к основам.
Обычная функция против асинхронной функции
Рассмотрим эти два примера. Оба примера выполняют сложение двух чисел: один с использованием обычных функций, а другой – удаленно.
Обычная функция для сложения двух чисел
Асинхронная функция для сложения двух чисел
Если вы складываете числа с помощью обычной функции, вы сразу получаете результат. Однако, когда вы делаете удаленный вызов для получения результата, вам нужно ждать, и вы не можете получить результат немедленно.
Вы не знаете, получите ли вы результат, так как сервер может быть недоступен, медленно отвечать и т.д. Вы не хотите, чтобы весь процесс блокировался, пока вы ждёте результат.
Вызов API, загрузка файлов и чтение файлов — это некоторые из обычных асинхронных операций, которые вы будете выполнять.
Вам не нужно использовать промисы для асинхронного вызова. До появления промисов мы использовали колбэки. Колбэки — это функция, которую вы вызываете, когда получаете результат. Давайте модифицируем предыдущий пример, чтобы принять колбэк.
Последующее асинхронное действие
Вместо того чтобы добавлять числа по одному, мы хотим добавить три раза. В обычной функции мы бы сделали это так:-
Вот как это выглядит с использованием колбэков:
Демо: https://jsbin.com/barimo/edit?html,js,console
Этот синтаксис менее удобен для пользователя из-за глубоко вложенных колбэков.
Избегание глубоко вложенных колбэков
Промисы могут помочь вам избежать глубоко вложенных колбэков. Давайте рассмотрим версию с промисами для того же примера:
С помощью промисов мы упрощаем коллбэки с использованием .then
. Таким образом, код выглядит чище, так как нет вложенности коллбэков. С синтаксисом ES7 async
вы можете еще больше улучшить этот пример.
Observable
Прежде чем остановиться на промисах, есть нечто, что поможет вам работать с асинхронными данными, называемое Observable
.
Давайте рассмотрим тот же пример, написанный с использованием Observable. В этом примере мы будем использовать RxJS для Observable.
Observable могут делать более интересные вещи. Например, с помощью delay
можно добавить задержку в 3 секунды
всего одной строкой кода или повторить вызов определенное количество раз.
Вы можете прочитать одну из моих статей о RxJs здесь.
Заключение
Ознакомление с колбэками и промисами важно. Понимайте их и используйте. Не беспокойтесь пока об Observable. Все три могут быть полезны в вашем развитии в зависимости от ситуации.
Source:
https://www.digitalocean.com/community/tutorials/understanding-javascript-promises