Промис (promise) - это объект, представляющий результат успешного или неудачного завершения асинхронной операции. Асинхронная операция, упрощенно говоря, это некоторое действие, выполняется независимо от окружающего ее кода, в котором она вызывается, не блокирует выполнение вызываемого кода.
Промис может находиться в одном из следующих состояний:
pending (состояние ожидания): начальное состояние, промис создан, но выполнение еще не завершено
fulfilled (успешно завершено): действие, которое представляет промис, успешно завершено
rejected (завершено с ошибкой): при выполнении действия, которое представляет промис, произошла ошибка
Для создания промиса применяется конструктор типа Promise:
new Promise(executor)
В качестве параметра конструктор принимает функцию, которая выполняется при создании промиса. Обычно эта функция представляет асинхронные операции, которые занимают продолжительное время. Например, определим простейший промис:
const myPromise = new Promise(function(){ console.log("Выполнение асинхронной операции"); });
Здесь функция просто выводит на консоль сообщение. Соответственно при выполнении этого кода мы увидим на консоли сообщение "Выполнение асинхронной операции"
.
При создании промиса, когда его функция еще не начала выполняться, промис переходит в состояние "pending", то есть ожидает выполнения.
Для эмуляции асинхронности определим несколько промисов:
const myPromise3000 = new Promise(function(){ console.log("[myPromise3000] Выполнение асинхронной операции"); setTimeout(()=>console.log("[myPromise3000] Завершение асинхронной операции"), 3000); }); const myPromise1000 = new Promise(function(){ console.log("[myPromise1000] Выполнение асинхронной операции"); setTimeout(()=>console.log("[myPromise1000] Завершение асинхронной операции"), 1000); }); const myPromise2000 = new Promise(function(){ console.log("[myPromise2000] Выполнение асинхронной операции"); setTimeout(()=>console.log("[myPromise2000] Завершение асинхронной операции"), 2000); });
Здесь определены три однотипных промиса. Чтобы каждый из них не выполнялся сразу, они используют функцию setTimeout с задержкой в несколько секунд. Для разных промисов длительность задержки различается. И в данном случае мы получим следующий консольный вывод:
[myPromise3000] Выполнение асинхронной операции [myPromise1000] Выполнение асинхронной операции [myPromise2000] Выполнение асинхронной операции [myPromise1000] Завершение асинхронной операции [myPromise2000] Завершение асинхронной операции [myPromise3000] Завершение асинхронной операции
Здесь мы видим, что первым начал выполняться промис myPromise3000, однако он же завершился последним, так как для него установлено наибольшее время задержки - 3 секунды. Однако его задержка не помешала выполнению остальных промисов.
Как правило, функция, которая передается в конструктор Promise, принимает два параметра:
const myPromise = new Promise(function(resolve, reject){ console.log("Выполнение асинхронной операции"); });
Оба этих параметра - resolve
и reject
также представляют функции. И каждая из этих функций принимает параметр любого типа.
Первый параметр - функция resolve
вызывается в случае успешного выполнения. Мы можем в нее передать значение, которое мы можем получить в результате
успешного выполнения.
Второй параметр - функция reject
вызывается, если выполнение операции завершилось с ошибкой. Мы можем в нее передать значение,
которое представит некоторую информацию об ошибке.
Итак, первый параметр функции в конструкторе Promise - функция resolve
выполняется при успешном выполненим. В эту функцию обычно передается значение, которое
представляет результат операции при успешном выполнении. Это значение может представлять любой объект. Например, передадим в эту функцию строку:
const myPromise = new Promise(function(resolve){ console.log("Выполнение асинхронной операции"); resolve("Привет мир!"); });
Функция resolve()
вызывается в конце выполняемой операции после всех действий. При вызове этой функции промис переходит в состояние
fulfilled
(успешно выполнено).
При этом стоит отметить, что теоретически мы можем возвратить из функции результат, но практического смысла в этом не будет:
const myPromise = new Promise(function(resolve, reject){ console.log("Выполнение асинхронной операции"); return "Привет мир!"; });
Данное возвращаемое значение мы не сможем передать во вне. И если действительно надо возвратить какой-то результат, то он передается в функцию resolve()
.
Второй параметр функции в конструкторе Promise - функция reject
вызывается при возникновении ошибки. В эту функцию обычно
передается некоторая информация об ошибке, которое может представлять любой объект. Например:
const myPromise = new Promise(function(resolve, reject){ console.log("Выполнение асинхронной операции"); reject("Переданы некорректные данные"); });
При вызове функции reject()
промис переходит в состояние
rejected
(завершилось с ошибкой).
Естественно мы можем определить логику, при которой в зависимости от условий будут выполняться обе функции:
const x = 4; const y = 0; const myPromise = new Promise(function(resolve, reject){ if(y === 0) { reject("Переданы некорректные данные"); } else{ const z = x / y; resolve(z); } });
В данном случае, если значени константы y
равно 0, то сообщаем об ошибке, вызывая функцию reject()
. Если не равно 0, то выполняем операцию деления
и передаем результат в функцию resolve()
.