что такое promise в javascript

Промисы

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

Чтобы получить передышку, вы обещаете разослать им сингл, когда он будет выпущен. Вы даёте фанатам список, в который они могут записаться. Они могут оставить там свой e-mail, чтобы получить песню, как только она выйдет. И даже больше: если что-то пойдёт не так, например, в студии будет пожар и песню выпустить не выйдет, они также получат уведомление об этом.

Все счастливы! Вы счастливы, потому что вас больше не донимают фанаты, а фанаты могут больше не беспокоиться, что пропустят новый сингл.

Это аналогия из реальной жизни для ситуаций, с которыми мы часто сталкиваемся в программировании:

Аналогия не совсем точна, потому что объект Promise в JavaScript гораздо сложнее простого списка подписок: он обладает дополнительными возможностями и ограничениями. Но для начала и такая аналогия хороша.

Синтаксис создания Promise :

Её аргументы resolve и reject – это колбэки, которые предоставляет сам JavaScript. Наш код – только внутри исполнителя.

Когда он получает результат, сейчас или позже – не важно, он должен вызвать один из этих колбэков:

Так что исполнитель по итогу переводит promise в одно из двух состояний:

Позже мы рассмотрим, как «фанаты» узнают об этих изменениях.

Ниже пример конструктора Promise и простого исполнителя с кодом, дающим результат с задержкой (через setTimeout ):

Мы можем наблюдать две вещи, запустив код выше:

Это был пример успешно выполненной задачи, в результате мы получили «успешно выполненный» промис.

А теперь пример, в котором исполнитель сообщит, что задача выполнена с ошибкой:

Промис – и успешный, и отклонённый будем называть «завершённым», в отличие от изначального промиса «в ожидании».

Все последующие вызовы resolve и reject будут проигнорированы:

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

Также заметим, что функция resolve / reject ожидает только один аргумент (или ни одного). Все дополнительные аргументы будут проигнорированы.

Это может случиться, например, когда мы начали выполнять какую-то задачу, но тут же увидели, что ранее её уже выполняли, и результат закеширован.

Потребители: then, catch, finally

Например, вот реакция на успешно выполненный промис:

Источник

Разбираемся с промисами в JavaScript

Доброго времени суток, Хабр! Представляю вашему вниманию перевод статьи «Understanding Promises in JavaScript» автора Sukhjinder Arora.

что такое promise в javascript. Смотреть фото что такое promise в javascript. Смотреть картинку что такое promise в javascript. Картинка про что такое promise в javascript. Фото что такое promise в javascript

От автора перевода: Так же, как и сам автор, я надеюсь, что статья оказалась для вас полезной. Пожалуйста, если она и вправду помогла вам узнать для себя что-то новое, то не поленитесь зайти на оригинал статьи и поблагодарить автора! Буду рад вашему фидбеку!

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

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

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

Здесь я запрашиваю некоторые данные с сервера при помощи функции getData(), которая получает данные внутри функции обратного вызова. Внутри функции обратного вызова я запрашиваю дополнительные данные при помощи вызова функции getMoreData(), передавая предыдущие данные как аргумент и так далее.

Это то, что мы называем “адом обратных вызовов”, где каждый обратный вызов вложен внутрь другого, и каждый внутренний обратный вызов зависит от его родителя.

Мы можем переписать приведенный выше фрагмент используя промисы:

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

Что такое Промисы?

Промис(Обещание) — это объект который содержит будущее значение асинхронной операции. Например, если вы запрашиваете некоторые данные с сервера, промис обещает нам получить эти данные, которые мы сможем использовать в будущем.

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

Состояния промисов

Промис в JavaScript, как и обещание в реальной жизни, имеет 3 состояния. Это может быть 1) нерешенный(в ожидании), 2) решенный/resolved (выполненный) или 3) отклоненный/rejected.

что такое promise в javascript. Смотреть фото что такое promise в javascript. Смотреть картинку что такое promise в javascript. Картинка про что такое promise в javascript. Фото что такое promise в javascript

Нерешенный или Ожидающий — Промис ожидает, если результат не готов. То есть, ожидает завершение чего-либо(например, завершения асинхронной операции).
Решенный или Выполненный — Промис решен, если результат доступен. То есть, что-то завершило свое выполнение(например, асинхронная операция) и все прошло хорошо.
Отклоненный — Промиc отклонен, если произошла ошибка в процессе выполнения.

Теперь мы знаем, что такое Промис и его терминологию, давайте вернемся назад к практической части промисов.

Создаем Промис

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

Мы создали новый промис, используя конструктор Промисов, он принимает один аргумент, обратный вызов, также известный как исполнительная функция, которая принимает 2 обратных вызова, resolve и reject.

Исполнительная функция выполняется сразу же после создания промиса. Промис становится выполненным при помощи вызова resolve(), а отклоненным при помощи reject(). Например:

resolve() и reject() принимают один аргумент, который может быть строкой, числом, логическим выражением, массивом или объектом.

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

Когда промис был создан, он будет в состоянии ожидания и его значение будет undefined.

что такое promise в javascript. Смотреть фото что такое promise в javascript. Смотреть картинку что такое promise в javascript. Картинка про что такое promise в javascript. Фото что такое promise в javascript

После 2 секунд таймер заканчивается, промис случайным образом либо выполняется, либо отклоняется, и его значением будет то, которое передано в функцию resolve или reject. Ниже пример двух случаев:

что такое promise в javascript. Смотреть фото что такое promise в javascript. Смотреть картинку что такое promise в javascript. Картинка про что такое promise в javascript. Фото что такое promise в javascript

что такое promise в javascript. Смотреть фото что такое promise в javascript. Смотреть картинку что такое promise в javascript. Картинка про что такое promise в javascript. Фото что такое promise в javascript

Примечание: Промис может быть выполнен или отклонен только один раз. Дальнейшие вызовы resolve() или reject() никак не повлияют на состояние промиса. Пример:

Так как resolve() была вызвана первой, то промис теперь получается статус “выполненный”. Последующий вызов reject() никак не повлияет на состояние промиса.

Использование Промиса

Теперь мы знаем как создавать промисы, давайте теперь разберемся как применять уже созданный промис. Мы используем промисы при помощи методов then() и catch().

Например, запрос данных из API при помощи fetch, которая возвращает промис.

.then() синтаксис: promise.then(successCallback, failureCallback)

successCallback вызывается, если промис был успешно выполнен. Принимает один аргумент, который является значением переданным в resolve().

failureCallback вызывается, если промис был отклонен. Принимает один аргумент, который является значением преданным в reject().

Если промис был выполнен, то вызывается successCallback со значением, переданным в resolve(). И если промис был отклонен, то вызывается failureCallback со значением, переданным в reject().

.catch() синтаксис: promise.catch(failureCallback)

Мы используем catch() для обработки ошибок. Это более читабельно, нежели обработка ошибок внутри failureCallback внутри обратного вызова метода then().

Цепочка промисов

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

Мы используем цепочку промисов, когда хотим выполнить последовательность промисов.

И так, что тут происходит?

Когда promise1 выполнен, вызывается метод then(), который возвращает promise2.
Далее, когда выполнен promise2, снова вызывается then() и возвращает promise3.

Так как promise3 отклонен, вместо следующего then(), вызывается catch(), который и обрабатывает отклонение promise3.

Примечание: Как правило достаточно одного метода catch() для обработки отклонения любого из промисов в цепочке, если этот метод находится в конце неё.

Распространенная ошибка

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

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

Promise.all( )

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

Здесь аргументом внутри then() выступает массив, который содержит значения промисов в том же порядке, в котором они передавались в Promise.all().(Только в том случае, если все промисы выполняются)

Промис отклоняется с причиной отклонения первого промиса в переданном массиве. Например:

Здесь у нас есть два промиса, где один выполняется через 2 секунды, а другой отклоняется через 1.5 секунды. Как только второй промис отклоняется, возвращенный от Promise.all() промис отклоняется не дожидаясь выполнения первого.

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

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

Promise.race( )

Этот метод принимает массив промисов и возвращает один новый промис, который будет выполненным, как только встретится выполненный промис в массиве или же отклоняется, если отклоненный промис встречается раньше. Например:

Тут мы имеем два промиса, где один выполняется через 1 секунду, а другой отклоняется через 1.5 секунды. Как только первый промис выполнен, возвращенный из Promise.race() промис будет иметь статус выполненного не дожидаясь статуса второго промиса.

Здесь data, которая передается в then() является значением первого, выполненного, промиса.

По итогу, Promise.race() дожидается первого промиса и берет его статус как статус возвращаемого промиса.

Комментарий автора перевода: Отсюда собственно и название. Race — гонка

Заключение

Мы узнали, что такое промисы и с чем их едят в JavaScript. Промисы состоят из двух частей 1) Создание промиса и 2) Использование промиса. Большую часть времени вы будете пользоваться промисами, нежели создавать их, но важно знать как они создаются.

Вот и все, надеюсь эта статья оказалась для вас полезной!

Источник

Promise

Сводка

Объект Promise используется для отложенных и асинхронных вычислений.

Синтаксис

Параметры

Описание

Интерфейс Promise (промис) представляет собой обёртку для значения, неизвестного на момент создания промиса. Он позволяет обрабатывать результаты асинхронных операций так, как если бы они были синхронными: вместо конечного результата асинхронного метода возвращается своего рода обещание (дословный перевод слова «промис») получить результат в некоторый момент в будущем.

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

Так как методы Promise.prototype.then() и Promise.prototype.catch() сами возвращают промис, их можно вызывать цепочкой, создавая соединения.

что такое promise в javascript. Смотреть фото что такое promise в javascript. Смотреть картинку что такое promise в javascript. Картинка про что такое promise в javascript. Фото что такое promise в javascript

Примечание: говорят, что промис находится в состоянии завершён (settled) когда он или исполнен или отклонён, т.е. в любом состоянии, кроме ожидания (это лишь форма речи, не являющаяся настоящим состоянием промиса). Также можно встретить термин исполнен (resolved) — это значит что промис завершён или «заблокирован» в ожидании завершения другого промиса. В статье состояния и fates приводится более подробное описание терминологии.

Свойства

Методы

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

Объект Promise создаётся при помощи ключевого слова new и своего конструктора. Конструктор Promise принимает в качестве аргумента функцию, называемую «исполнитель» (executor function). Эта функция должна принимать две функции-колбэка в качестве параметров. Первый из них ( resolve ) вызывается, когда асинхронная операция завершилась успешно и вернула результат своего исполнения в виде значения. Второй колбэк ( reject ) вызывается, когда операция не удалась, и возвращает значение, указывающее на причину неудачи, чаще всего объект ошибки.

Чтобы снабдить функцию функциональностью промисов, нужно просто вернуть в ней объект Promise :

Источник

Promise

Материал на этой странице устарел, поэтому скрыт из оглавления сайта.

Более новая информация по этой теме находится на странице https://learn.javascript.ru/promise-basics.

Promise (обычно их так и называют «промисы») – предоставляют удобный способ организации асинхронного кода.

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

Что такое Promise?

Promise – это специальный объект, который содержит своё состояние. Вначале pending («ожидание»), затем – одно из: fulfilled («выполнено успешно») или rejected («выполнено с ошибкой»).

что такое promise в javascript. Смотреть фото что такое promise в javascript. Смотреть картинку что такое promise в javascript. Картинка про что такое promise в javascript. Фото что такое promise в javascript

На promise можно навешивать колбэки двух типов:

Способ использования, в общих чертах, такой:

Синтаксис создания Promise :

Универсальный метод для навешивания обработчиков:

С его помощью можно назначить как оба обработчика сразу, так и только один:

Если в функции промиса происходит синхронный throw (или иная ошибка), то вызывается reject :

Посмотрим, как это выглядит вместе, на простом примере.

Пример с setTimeout

Возьмём setTimeout в качестве асинхронной операции, которая должна через некоторое время успешно завершиться с результатом «result»:

В результате запуска кода выше – через 1 секунду выведется «Fulfilled: result».

Функции resolve/reject принимают ровно один аргумент – результат/ошибку.

Promise после reject/resolve – неизменны

Заметим, что после вызова resolve/reject промис уже не может «передумать».

Когда промис переходит в состояние «выполнен» – с результатом (resolve) или ошибкой (reject) – это навсегда.

Последующие вызовы resolve/reject будут просто проигнорированы.

А так – наоборот, ошибка будет раньше:

Промисификация

Промисификация – это когда берут асинхронную функциональность и делают для неё обёртку, возвращающую промис.

После промисификации использование функциональности зачастую становится гораздо удобнее.

В качестве примера сделаем такую обёртку для запросов при помощи XMLHttpRequest.

Функция httpGet(url) будет возвращать промис, который при успешной загрузке данных с url будет переходить в fulfilled с этими данными, а при ошибке – в rejected с информацией об ошибке:

Цепочки промисов

«Чейнинг» (chaining), то есть возможность строить асинхронные цепочки из промисов – пожалуй, основная причина, из-за которой существуют и активно используются промисы.

Например, мы хотим по очереди:

Самое главное в этом коде – последовательность вызовов:

Если очередной then вернул промис, то далее по цепочке будет передан не сам этот промис, а его результат.

Схематично его работу можно изобразить так:

что такое promise в javascript. Смотреть фото что такое promise в javascript. Смотреть картинку что такое promise в javascript. Картинка про что такое promise в javascript. Фото что такое promise в javascript

Значком «песочные часы» помечены периоды ожидания, которых всего два: в исходном httpGet и в подвызове далее по цепочке.

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

То есть, логика довольно проста:

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

Строку (*) для этого нужно переписать так:

Перехват ошибок

Выше мы рассмотрели «идеальный случай» выполнения, когда ошибок нет.

А что, если github не отвечает? Или JSON.parse бросил синтаксическую ошибку при обработке данных?

Да мало ли, где ошибка…

Правило здесь очень простое.

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

Есть два варианта развития событий:

Промисы в деталях

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

Чтобы наше понимание промисов было полным, и мы могли с лёгкостью разрешать сложные ситуации, посмотрим внимательнее, что такое промис и как он работает, но уже не в общих словах, а детально, в соответствии со стандартом ECMAScript.

Согласно стандарту, у объекта new Promise(executor) при создании есть четыре внутренних свойства:

что такое promise в javascript. Смотреть фото что такое promise в javascript. Смотреть картинку что такое promise в javascript. Картинка про что такое promise в javascript. Фото что такое promise в javascript

Он делает следующее:

Здесь важно, что обработчики можно добавлять в любой момент. Можно до выполнения промиса (они подождут), а можно – после (выполнятся в ближайшее время, через асинхронную очередь).

Источник

Знакомство с промисами в JavaScript

что такое promise в javascript. Смотреть фото что такое promise в javascript. Смотреть картинку что такое promise в javascript. Картинка про что такое promise в javascript. Фото что такое promise в javascript

Jan 15, 2020 · 4 min read

что такое promise в javascript. Смотреть фото что такое promise в javascript. Смотреть картинку что такое promise в javascript. Картинка про что такое promise в javascript. Фото что такое promise в javascript

Если вы не совсем в курсе современных тенденций JavaScript, то, по крайней мере, слышали о промисах ранее, но не знаете, где и как их можно было бы применить.

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

Проблема обратных вызовов

Хотя промисы и существую т уже на протяжении нескольких лет, давайте все же вспомним времена, когда их не было. Это поможет лучше понять, почему они являются хорошим способом управления асинхронными операциями.

Изначально для этого применялись функции обратного вызова. Они были наиболее удобными в этом отношении, но все равно имели ряд недостатков. Давайте взглянем на такой пример:

Как вы видите, функция loadScript передается параметром обратного вызова, который выполняется после загрузки скрипта. Все это работает прекрасно, но возникает один большой вопрос: “Что случится, если скрипт по какой-либо причине не загрузится?”. Со стороны разработчика будет наивным игнорировать такую возможность.

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

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

Именно такие ситуации и приводят к возникновению кошмара в обратных вызовах.

Краткое введение

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

“Объект Promise представляет окончательное выполнение (или провал) асинхронной операции, а также ее итоговое значение.”

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

Промис может иметь одно из четырех состояний:

Промисы в коде

Теперь давайте создадим простой пример промиса для лучшего понимания:

В этом примере мы пробуем запросить данные из API. Если API вернет HTTP код состояния 200, значит запрос оказался успешным. В противном случае он провалился.

Как же нам применять промис, который мы только что создали?

All и Race

Идеальным примером применения Promise.all может выступить одновременная множественная отправка AJAX запросов.

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *