Сводка
Объект Promise (обещание) используется для отложенных и асинхронных вычислений. Promise может находиться в трёх состояниях:
- ожидание (pending): начальное состояние, не выполнено и не отклонено.
- выполнено (fulfilled): операция завершена успешно.
- отклонено (rejected): операция завершена с ошибкой.
Другой термин, описывающий состояние заданный (settled): обещание выполнено или отклонено, но не находится в состоянии ожидания.
Синтаксис
new Promise(executor);
new Promise(function(resolve, reject) { ... });
Параметры
- executor
- Объект функции с двумя аргументами
resolveиreject. Первый аргумент вызывает успешное выполнение обещания, второй отклоняет его. Мы можем вызывать эти функции по завершении нашей операции.
Описание
Интерфейс Promise (обещание) представляет собой обертку для значения, неизвестного на момент создания обещания. Он позволяет обрабатывать результаты асинхронных операций так, как если бы они были синхронными: вместо конечного результата асинхронного метода возвращается обещание получить результат в некоторый момент в будущем.
При создании обещание находится в ожидании (pending), а затем может стать выполнено (fulfilled), вернув полученный результат (значение), или отклонено (rejected), вернув причину отказа. В любом из этих случаев вызывается обработчик, прикрепленный к обещанию методом then . Если в момент прикрепления обработчика обещание уже сдержано или нарушено, он все равно будет выполнен, т.е. между выполнением обещания и прикреплением обработчика нет «состояния гонки», как, например, в случае с событиями в DOM.
Так как методы Promise.prototype.then и Promise.prototype.catch сами возвращают обещания, их можно вызывать цепочкой, создавая соединения.

Свойства
Promise.length- Значение свойства всегда равно 1 (количество аргументов конструктора).
Promise.prototype- Представляет прототип для конструктора
Promise.
Методы
Promise.all(iterable)- Возвращает обещание, которое выполнится после выполнения всех обещаний в передаваемом итерируемом аргументе.
Promise.race(iterable)- Возвращает обещание, которое будет выполнено или отклонено с результатом исполнения первого выполненного или отклонённого итерируемого обещания.
Promise.reject(reason)- Возвращает объект
Promise, который отклонён с указанной причиной.
Promise.resolve(value)- Возвращает объект
Promise, который выполнен с указанным значением. Если значение может быть продолжено (имеется методthen), то возвращаемое обещание будет "следовать" продолжению, выступая адаптером его состояния; в противном случае будет возвращено ожидание в выполненном состоянии.
Прототип Promise
Свойства
Promise.prototype.constructor- Возвращает функцию, которая создала прототип экземпляра. Это функция всех обещаний по умолчанию.
Методы
Promise.prototype.catch(onRejected)- Добавляет функцию обратного вызова, для обработки отклонения обещания, которая возвращает новое обещание выполненное с переданным значением, если она вызвана, или оригинальное значение resolve, если обещание выполнено.
Promise.prototype.then(onFulfilled, onRejected)- Добавляет обработчик выполнения и отклонения обещания, и возвращает новое обещание выполненное со значением вызванного обработчика, или оригинальное значение, если обещание не было обработано (т.е. если соответствующий обработчик onFulfilled или onRejected не является функцией).
Создание обещания
Объект Promise создается при помощи ключевого слова new и своего конструктора. Конструктор Promise принимает в качестве аргумента функцию, называемую "исполнитель" (executor function). Эта функция должна принимать две функции-коллбэка в качестве параметров. Первый из них (resolve) вызывается, когда асинхронная операция завершилась успешно и вернула результат своего исполнения в виде значения. Второй коллбэк (reject) вызывается, когда операция не удалась, и возвращает значение, указывающее на причину неудачи, чаще всего объект ошибки.
const myFirstPromise = new Promise((resolve, reject) => {
// выполняется асинхронная операция, которая в итоге вызовет:
//
// resolve(someValue); // успешное завершение
// или
// reject("failure reason"); // неудача
});
Чтобы снабдить функцию функционалом обещаний, нужно просто вернуть в ней объект Promise:
function myAsyncFunction(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onload = () => resolve(xhr.responseText);
xhr.onerror = () => reject(xhr.statusText);
xhr.send();
});
}
Примеры
Простой пример
let myFirstPromise = new Promise((resolve, reject) => {
// Мы вызываем resolve(...), когда асинхронная операция завершилась успешно, и reject(...), когда она не удалась.
// В этом примере мы используем setTimeout(...), чтобы симулировать асинхронный код.
// В реальности вы, скорее всего, будете использовать XHR, HTML5 API или что-то подобное.
setTimeout(function(){
resolve("Success!"); // Ура! Всё прошло хорошо!
}, 250);
});
myFirstPromise.then((successMessage) => {
// successMessage - это что угодно, что мы передали в функцию resolve(...) выше.
// Это необязательно строка, но если это всего лишь сообщение об успешном завершении, это наверняка будет она.
console.log("Ура! " + successMessage);
});
Продвинутый пример
<button id="btn">Создать Promise!</button>
<div id="log"></div>
Данный небольшой пример показывает механизм работы с Promise. Метод testPromise() вызывается при каждом нажатии на <button>. При этом создаётся обещание, которое успешно выполняется при помощи window.setTimeout, со значением 'result' в случайном интервале от 1 до 3-х секунд.
Выполнение обещания протоколируется при помощи продолжения p1.then. Это показывает как синхронная часть метода отвязана от асинхронного завершения обещания.
var promiseCount = 0;
function testPromise() {
var thisPromiseCount = ++promiseCount;
var log = document.getElementById('log');
log.insertAdjacentHTML('beforeend', thisPromiseCount +
') Запуск (запуск синхронного кода)
');
// Создаём обещание, возвращающее 'result' (по истечении 3-х секунд)
var p1 = new Promise(
// Функция разрешения позволяет завершить успешно или
// отклонить обещание
function(resolve, reject) {
log.insertAdjacentHTML('beforeend', thisPromiseCount +
') Запуск обещания (запуск асинхронного кода)
');
// Это всего лишь пример асинхронности
window.setTimeout(
function() {
// Обещание выполнено!
resolve(thisPromiseCount)
}, Math.random() * 2000 + 1000);
});
// Указываем, что сделать с выполненным обещанием
p1.then(
// Записываем в протокол
function(val) {
log.insertAdjacentHTML('beforeend', val +
') Обещание выполнено (асинхронный код завершён)
');
});
log.insertAdjacentHTML('beforeend', thisPromiseCount +
') Обещание создано (синхронный код завершён)
');
}
if ("Promise" in window) {
let btn = document.getElementById("btn");
btn.addEventListener("click",testPromise);
} else {
log = document.getElementById('log');
log.innerHTML = "Демонстрация невозможна, поскольку ваш браузер не поддерживает интерфейс <code>Promise<code>.";
}
Данный пример запускается при нажатии на кнопку. Для этого вам необходим браузер, поддерживающий Promise. При последовательных нажатиях на кнопку с коротким интервалом, вы можете увидеть как различные обещания будут выполнены один за другим.
Загрузка изображения при помощи XHR
Другой простой пример использования Promise и XMLHttpRequest для загрузки изображения доступен в репозитории MDNpromise-test на GitHub. Вы также можете посмотреть его в действии. Каждый шаг прокомментирован и вы можете подробно исследовать Promise и XHR.
Спецификации
| Спецификация | Статус | Комментарий |
|---|---|---|
| domenic/promises-unwrapping | Черновик | Начало работы над стандартом. |
| ECMAScript 2015 (6th Edition, ECMA-262) Определение 'Promise' в этой спецификации. |
Стандарт | Изначальное определение в стандарте ECMA. |
Совместимость с браузерами
| Компьютеры | Мобильные | Server | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Promise | Chrome Полная поддержка 32 | Edge Полная поддержка Да | Firefox Полная поддержка 29 | IE Нет поддержки Нет | Opera Полная поддержка 19 | Safari Полная поддержка 8 | WebView Android Полная поддержка 4.4.3 | Chrome Android Полная поддержка 32 | Firefox Android Полная поддержка 29 | Opera Android Полная поддержка Да | Safari iOS Полная поддержка 8 | Samsung Internet Android Полная поддержка Да | nodejs Полная поддержка 0.12 |
Promise() constructor | Chrome Полная поддержка 32 | Edge Полная поддержка Да | Firefox
Полная поддержка
29
| IE Нет поддержки Нет | Opera Полная поддержка 19 | Safari
Полная поддержка
8
| WebView Android Полная поддержка 4.4.3 | Chrome Android Полная поддержка 32 | Firefox Android
Полная поддержка
29
| Opera Android Полная поддержка Да | Safari iOS
Полная поддержка
8
| Samsung Internet Android Полная поддержка Да | nodejs
Полная поддержка
0.12
|
all() | Chrome Полная поддержка 32 | Edge Полная поддержка 12 | Firefox Полная поддержка 29 | IE Нет поддержки Нет | Opera Полная поддержка 19 | Safari Полная поддержка 8 | WebView Android Полная поддержка 4.4.3 | Chrome Android Полная поддержка 32 | Firefox Android Полная поддержка 29 | Opera Android Полная поддержка Да | Safari iOS Полная поддержка 8 | Samsung Internet Android Полная поддержка Да | nodejs Полная поддержка 0.12 |
allSettled() | Chrome Полная поддержка 76 | Edge Нет поддержки Нет | Firefox Нет поддержки Нет | IE Нет поддержки Нет | Opera ? | Safari ? | WebView Android Полная поддержка 76 | Chrome Android Полная поддержка 76 | Firefox Android Нет поддержки Нет | Opera Android Полная поддержка Да | Safari iOS ? | Samsung Internet Android ? | nodejs ? |
prototype | Chrome Полная поддержка 32 | Edge Полная поддержка Да | Firefox Полная поддержка 29 | IE Нет поддержки Нет | Opera Полная поддержка 19 | Safari Полная поддержка 8 | WebView Android Полная поддержка 4.4.3 | Chrome Android Полная поддержка 32 | Firefox Android Полная поддержка 29 | Opera Android Полная поддержка Да | Safari iOS Полная поддержка 8 | Samsung Internet Android Полная поддержка Да | nodejs Полная поддержка 0.12 |
catch() | Chrome Полная поддержка 32 | Edge Полная поддержка 12 | Firefox Полная поддержка 29 | IE Нет поддержки Нет | Opera Полная поддержка 19 | Safari Полная поддержка 8 | WebView Android Полная поддержка 4.4.3 | Chrome Android Полная поддержка 32 | Firefox Android Полная поддержка 29 | Opera Android Полная поддержка Да | Safari iOS Полная поддержка 8 | Samsung Internet Android Полная поддержка Да | nodejs Полная поддержка 0.12 |
finally() | Chrome Полная поддержка 63 | Edge Полная поддержка 18 | Firefox Полная поддержка 58 | IE Нет поддержки Нет | Opera Полная поддержка 50 | Safari Полная поддержка 11.1 | WebView Android Полная поддержка 63 | Chrome Android Полная поддержка 63 | Firefox Android Полная поддержка 58 | Opera Android Полная поддержка 46 | Safari iOS Полная поддержка 11.1 | Samsung Internet Android Нет поддержки Нет | nodejs Полная поддержка 10.0.0 |
then() | Chrome Полная поддержка 32 | Edge Полная поддержка 12 | Firefox Полная поддержка 29 | IE Нет поддержки Нет | Opera Полная поддержка 19 | Safari Полная поддержка 8 | WebView Android Полная поддержка 4.4.3 | Chrome Android Полная поддержка 32 | Firefox Android Полная поддержка 29 | Opera Android Полная поддержка Да | Safari iOS Полная поддержка 8 | Samsung Internet Android Полная поддержка Да | nodejs Полная поддержка 0.12 |
race() | Chrome Полная поддержка 32 | Edge Полная поддержка 12 | Firefox Полная поддержка 29 | IE Нет поддержки Нет | Opera Полная поддержка 19 | Safari Полная поддержка 8 | WebView Android Полная поддержка 4.4.3 | Chrome Android Полная поддержка 32 | Firefox Android Полная поддержка 29 | Opera Android Полная поддержка Да | Safari iOS Полная поддержка 8 | Samsung Internet Android Полная поддержка Да | nodejs Полная поддержка 0.12 |
reject() | Chrome Полная поддержка 32 | Edge Полная поддержка 12 | Firefox Полная поддержка 29 | IE Нет поддержки Нет | Opera Полная поддержка 19 | Safari Полная поддержка 8 | WebView Android Полная поддержка 4.4.3 | Chrome Android Полная поддержка 32 | Firefox Android Полная поддержка 29 | Opera Android Полная поддержка Да | Safari iOS Полная поддержка 8 | Samsung Internet Android Полная поддержка Да | nodejs Полная поддержка 0.12 |
resolve() | Chrome Полная поддержка 32 | Edge Полная поддержка 12 | Firefox Полная поддержка 29 | IE Нет поддержки Нет | Opera Полная поддержка 19 | Safari Полная поддержка 8 | WebView Android Полная поддержка 4.4.3 | Chrome Android Полная поддержка 32 | Firefox Android Полная поддержка 29 | Opera Android Полная поддержка Да | Safari iOS Полная поддержка 8 | Samsung Internet Android Полная поддержка Да | nodejs Полная поддержка 0.12 |
Легенда
- Полная поддержка
- Полная поддержка
- Нет поддержки
- Нет поддержки
- Совместимость неизвестна
- Совместимость неизвестна
- Смотрите замечания реализации.
- Смотрите замечания реализации.
Смотрите также
- Спецификация Promises/A+
- Jake Archibald: JavaScript Promises: There and Back Again
- Domenic Denicola: Callbacks, Promises, and Coroutines – Asynchronous Programming Pattern in JavaScript
- Matt Greer: JavaScript Promises ... In Wicked Detail
- Forbes Lindesay: promisejs.org
- Nolan Lawson: We have a problem with promises — Common mistakes with promises
- Promise polyfill
- Udacity: JavaScript Promises