Promise

Автор:Игорь Тельменко

Promise

Promise (промисы) - удобный механизм организации асинхронного кода.

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

Чтобы нам понадобилось при этом. Несколько вложенных двуг в друга callback-функций (обработчиков). Такой код стал бы плохочитаемым. Так же, на бы хотелось иметь обработку ошибок. Для этого пришлось бы добавлять callback-функции и для ошибочных ситуаций. Для решения этой проблемы и существуют промисы.

С помощью них мы можем выстаивать цепочками асинхронные вызовы. Тоесть работать с ними как с синхронным кодом.

Демонстрация простейшего promise:

Здесь роль асинхронного кода выполняет setTimeout(). В консоли выведется строка "Work is finished", так как этот вариант сработает быстрее (имеет меньшую задержку). Вариант с выводом строки "Time is up" не выведется вообще, так как промис имеет таое свойтсво как состояние. Есть три состояния: ожидание (pending), выполнено успешно (fulfilled), завершено с ошибкой (rejected). При помощи вызова resolve() мы переводим промис в успешное состояние. И вызовом reject() - в состояние ошибки. Из состояния ожидания (в котором промис находится сразу) промис может перейти либо в состояние успеха либо в состояние ошибки. Что произошло ранее, то и будет конечным состоянием. Таким образом, в примере выше мы можем управлять тем, что в итоге выведется в консоли, путем регулировки времени срабатывания.

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

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

Тоесть структура подобных операций такая:

Правда могут быть и вызовы catch(). Но это просто алиасы к then(null, ...).

Как мы видим, данные после одного асинхронного запроса используются в другом, затем в третьем и так далее.

Но что в случае, если произошла ошибка? В таком случае происходит переход к ближайшему обработчику состояния rejected. Причем он может быть задан как вторым параметром then(), так и вызовом catch(). А в этом обработчике, если мы просто вернем какое-либо значение через return, то управление передет к ближайшему then(). Если же мы вместо этого выбросим исключение через throw, то ошибка переходит в следующий ближайший обработчик rejected.

Кроме then() и catch() есть еще кое-какие полезные методы:

  • Promise.all(iterable) - возвращает promise, который выполнится после выполнения всех промисов в передаваемом итерируемом (например массив) аргументе.
  • Promise.race(iterable) - возвращаетpromise, который выполнится или будет отклонен с результатом исполнения первого выполненного или отклонённого итерируемого промиса.

Оставить ответ