Promise
Базовый Широко доступен
Эта функция хорошо зарекомендовала себя и работает на многих устройствах и в разных версиях браузеров. Она доступна в браузерах с июля 2015 года.
Объект Promise представляет собой eventual completion (или failure) асинхронной операции и ее результат.
Чтобы узнать, как работают промисы и как их можно использовать, мы рекомендуем сначала прочитать Использование промисов.
Описание
Promise — это прокси для значения, которое не обязательно известно на момент создания промиса. Он позволяет ассоциировать обработчики с конечным успешным значением или причиной отказа асинхронного действия. Это позволяет асинхронным методам возвращать значения, как и синхронные методы: вместо немедленного возврата окончательного значения, асинхронный метод возвращает промис, который предоставит значение в будущем.
Promise находится в одном из следующих состояний:
- pending: начальное состояние, ни не выполненное, ни отклоненное.
- fulfilled: означает, что операция была успешно завершена.
- rejected: означает, что операция не удалась.
Конечное состояние ожидающего промиса может быть либо выполнено со значением, либо отклонено с причиной (ошибкой). Когда происходит один из этих вариантов, вызываются соответствующие обработчики, поставленные в очередь методом then промиса. Если промис уже был выполнен или отклонен при подключении соответствующего обработчика, обработчик будет вызван, поэтому нет состояния гонки между завершением асинхронной операции и подключением ее обработчиков.
Говорят, что промис settled (установлен), если он либо выполнен, либо отклонен, но не находится в состоянии ожидания.

Вы также услышите термин resolved (разрешенный) применительно к промисам — это означает, что промис установлен или "зафиксирован" в соответствии с конечным состоянием другого промиса, и дальнейшее его разрешение или отклонение не имеет эффекта. Документ States and fates из первоначального предложения Promise содержит более подробную информацию о терминологии промисов. В разговорной речи "разрешенные" промисы часто эквивалентны "выполненным" промисам, но, как показано в "States and fates", разрешенные промисы также могут быть в состоянии ожидания или отклонены. Например:
new Promise((resolveOuter) => {
resolveOuter(
new Promise((resolveInner) => {
setTimeout(resolveInner, 1000);
}),
);
});
Этот промис уже разрешен на момент создания (поскольку resolveOuter вызывается синхронно), но он разрешен другим промисом и поэтому не будет выполнен до 1 секунды спустя, когда внутренний промис выполнится. На практике "разрешение" часто происходит за кулисами и не наблюдается, наблюдаются только его выполнение или отклонение.
Примечание: Несколько других языков имеют механизмы для ленивых вычислений и отложенных вычислений, которые они также называют "промисами", например, Scheme. Промисы в JavaScript представляют собой процессы, которые уже происходят и могут быть связаны с функциями обратного вызова. Если вы хотите лениво вычислить выражение, рассмотрите возможность использования функции без аргументов, например f = () => expression, для создания лениво вычисляемого выражения и f() для немедленного вычисления выражения.
Promise сам по себе не имеет первоклассного протокола для отмены, но вы можете иметь возможность напрямую отменить базовую асинхронную операцию, как правило, используя AbortController.
Цепочки промисов
Методы промисов then(), catch() и finally() используются для привязки дальнейших действий к промису, который достиг конечного состояния. Метод then() принимает до двух аргументов; первый аргумент — это функция обратного вызова для случая успешного выполнения промиса, а второй аргумент — функция обратного вызова для случая отклонения. Методы catch() и finally() внутренне вызывают then() и делают обработку ошибок менее многословной. Например, catch() — это, по сути, then() без передачи обработчика выполнения. Поскольку эти методы возвращают промисы, их можно объединять в цепочки. Например:
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("foo");
}, 300);
});
myPromise
.then(handleFulfilledA, handleRejectedA)
.then(handleFulfilledB, handleRejectedB)
.then(handleFulfilledC, handleRejectedC);
Мы будем использовать следующую терминологию: исходный промис — это промис, у которого вызывается then; новый промис — это промис, возвращаемый then. Два обработчика, передаваемых в then, называются обработчик выполнения и обработчик отклонения соответственно.
Конечное состояние исходного промиса определяет, какой обработчик будет выполнен.
- Если исходный промис выполнен, обработчик выполнения вызывается с значением выполнения.
- Если исходный промис отклонен, обработчик отклонения вызывается с причиной отклонения.
Завершение обработчика определяет конечное состояние нового промиса.
- Если обработчик возвращает значение thenable, новый промис устанавливается в то же состояние, что и возвращаемое значение.
- Если обработчик возвращает не-thenable значение, новый промис выполняется с возвращаемым значением.
- Если обработчик выбрасывает ошибку, новый промис отклоняется с выброшенной ошибкой.
- Если для исходного промиса не прикреплен соответствующий обработчик, новый промис будет установлен в то же состояние, что и исходный промис — то есть, без обработчика отклонения, отклоненный промис остается отклоненным с той же причиной.
Например, в приведенном выше коде, если myPromise отклонен, будет вызван handleRejectedA, и если handleRejectedA завершится нормально (без выбрасывания исключения или возврата отклоненного промиса), промис, возвращаемый первым then, будет выполнен, а не останется отклоненным. Поэтому, если ошибку нужно обработать немедленно, но мы хотим сохранить состояние ошибки в цепочке, мы должны выбросить ошибку определенного типа в обработчике отклонения. С другой стороны, при отсутствии немедленной необходимости, мы можем опустить обработку ошибок до последнего обработчика catch().
myPromise .then(handleFulfilledA) .then(handleFulfilledB) .then(handleFulfilledC) .catch(handleRejectedAny);
Используя стрелочные функции для функций обратного вызова, реализация цепочки промисов может выглядеть примерно так:
myPromise
.then((value) => `${value} and bar`)
.then((value) => `${value} and bar again`)
.then((value) => `${value} and again`)
.then((value) => `${value} and again`)
.then((value) => {
console.log(value);
})
.catch((err) => {
console.error(err);
});
Примечание: Для более быстрой работы все синхронные действия предпочтительно должны выполняться в одном обработчике, иначе для последовательного выполнения всех обработчиков потребуется несколько тиков.
JavaScript поддерживает очередь заданий. Каждый раз JavaScript выбирает задание из очереди и выполняет его до завершения. Задания определяются исполнителем конструктора Promise(), обработчиками, переданными в then, или любым API платформы, возвращающим промис. Промисы в цепочке представляют отношение зависимости между этими заданиями. Когда промис устанавливается, соответствующие обработчики, связанные с ним, добавляются в конец очереди заданий.
Промис может участвовать в более чем одной цепочке. Для следующего кода выполнение promiseA приведет к добавлению handleFulfilled1 и handleFulfilled2 в очередь заданий. Поскольку handleFulfilled1 зарегистрирован первым, он будет вызван первым.
const promiseA = new Promise(myExecutorFunc); const promiseB = promiseA.then(handleFulfilled1, handleRejected1); const promiseC = promiseA.then(handleFulfilled2, handleRejected2);
Действие может быть назначено уже установленному промису. В этом случае действие немедленно добавляется в конец очереди заданий и будет выполнено, когда все существующие задания будут завершены. Поэтому действие для уже "установленного" промиса произойдет только после завершения текущего синхронного кода и пройдет как минимум один тик цикла. Это гарантирует, что действия промисов являются асинхронными.
const promiseA = new Promise((resolve, reject) => {
resolve(777);
});
// At this point, "promiseA" is already settled.
promiseA.then((val) => console.log("asynchronous logging has val:", val));
console.log("immediate logging");
// produces output in this order:
// immediate logging
// asynchronous logging has val: 777
Thenables
Экосистема JavaScript имела несколько реализаций Promise задолго до того, как они стали частью языка. Несмотря на то, что они внутренне представляются по-разному, как минимум, все объекты, похожие на Promise, реализуют интерфейс Thenable. Thenable реализует метод .then(), который вызывается с двумя функциями обратного вызова: одна для случая выполнения промиса, другая для случая отклонения. Промисы также являются thenables.
Для взаимодействия с существующими реализациями Promise язык позволяет использовать thenables вместо промисов. Например, Promise.resolve не только разрешает промисы, но и отслеживает thenables.
// This is not a Promises/A+ compliant thenable! It calls onFulfilled
// synchronously. For demonstration only.
const thenable = {
then(onFulfilled, onRejected) {
onFulfilled({
// The thenable is fulfilled with another thenable
then(onFulfilled, onRejected) {
onFulfilled(42);
},
});
},
};
Promise.resolve(thenable); // A promise fulfilled with 42
Метод then() отвечает за планирование выполнения предоставленных колбэков onFulfilled и onRejected. Его семантика, включая обработку ошибок и асинхронность, точно определена в спецификации Promises/A+, и мы не будем повторять их здесь. Очень редко возникает необходимость реализовать thenable самостоятельно; даже если вы не используете нативные промисы, вы, вероятно, будете использовать библиотеку Promise, такую как Bluebird.
Параллелизм промисов
Класс Promise предлагает четыре основных статических метода для облегчения параллелизма асинхронных задач:
-
Promise.all() - Выполняется, когда все промисы выполнены; отклоняется, когда любой из промисов отклонен.
-
Promise.allSettled() - Выполняется, когда все промисы установлены.
-
Promise.any() - Выполняется, когда любой из промисов выполнен; отклоняется, когда все промисы отклонены.
-
Promise.race() - Устанавливается, когда любой из промисов устанавливается. Другими словами, выполняется, когда любой из промисов выполняется; отклоняется, когда любой из промисов отклоняется.
Все эти методы принимают итерируемый набор промисов (точнее, thenables) и возвращают новый промис. Все они поддерживают подклассинг, что означает, что их можно вызывать для подклассов Promise, и результатом будет промис подкласса. Для этого конструктор подкласса должен реализовывать ту же сигнатуру, что и конструктор Promise() — принимая единственную функцию executor, которую можно вызвать с параметрами resolve и reject. Подкласс также должен иметь статический метод resolve, который можно вызывать как Promise.resolve() для разрешения значений в промисы.
Существуют два других удобных статических метода: Promise.allKeyed() и Promise.allSettledKeyed(), которые ведут себя как Promise.all() и Promise.allSettled(), но принимают объекты промисов и возвращают промисы, которые выполняются с объектами той же формы. Работая с объектами вместо массивов, вы можете связывать результаты с семантически значимыми ключами, а не с произвольным порядком массива, который может быть сложно поддерживать.
Эти методы прикрепляют обработчики к каждому входному промису с помощью then(). Даже когда результирующий промис установлен рано (например, когда один вход в Promise.race() установлен), другие обработчики не удаляются. Повторная передача одного и того же ожидающего промиса в методы параллелизма может накапливать обработчики, даже если эти обработчики никогда не используются:
const pendingPromise = new Promise(() => {});
for (let i = 0; i < 1000; i++) {
await Promise.race([Promise.resolve(0), pendingPromise]);
}
// All tasks have completed, but pendingPromise retains the
// handlers attached by all 1000 races.
Промисы не предоставляют способа отписаться от этих обработчиков; они остаются прикрепленными, пока входной промис находится в состоянии ожидания и доступен. Где это возможно, отменяйте базовую операцию, используя AbortSignal, когда ожидающий промис больше не нужен.
Обратите внимание, что JavaScript по своей природе однопоточный, поэтому в данный момент выполняется только одна задача, хотя управление может переключаться между различными промисами, что делает выполнение промисов кажущимся параллельным. Параллельное выполнение в JavaScript может быть достигнуто только через рабочие потоки.
Конструктор
-
Promise() - Создает новый объект
Promise. Конструктор в основном используется для обертывания функций, которые еще не поддерживают промисы.
Статические свойства
-
Promise[Symbol.species] - Возвращает конструктор, используемый для создания возвращаемых значений из методов промисов.
Статические методы
-
Promise.all() - Принимает итерируемый набор промисов в качестве входных данных и возвращает один
Promise. Этот возвращаемый промис выполняется, когда все входные промисы выполняются (включая случай, когда передается пустой итерируемый набор), с массивом значений выполнения. Он отклоняется, когда любой из входных промисов отклоняется, с первой причиной отклонения. -
Promise.allKeyed()Экспериментальный - Подобно
Promise.all(), за исключением того, что он принимает объект промисов и возвращает промис, который выполняется с объектом той же формы, позволяя вам связывать результаты с семантически значимыми ключами. -
Promise.allSettled() - Принимает итерируемый набор промисов в качестве входных данных и возвращает один
Promise. Этот возвращаемый промис выполняется, когда все входные промисы устанавливаются (включая случай, когда передается пустой итерируемый набор), с массивом объектов, описывающих результат каждого промиса. -
Promise.allSettledKeyed()Экспериментальный - Подобно
Promise.allSettled(), за исключением того, что он принимает объект промисов и возвращает промис, который выполняется с объектом той же формы, позволяя вам связывать результаты с семантически значимыми ключами. -
Promise.any() - Принимает итерируемый набор промисов в качестве входных данных и возвращает один
Promise. Этот возвращаемый промис выполняется, когда любой из входных промисов выполняется, с этим первым значением выполнения. Он отклоняется, когда все входные промисы отклоняются (включая случай, когда передается пустой итерируемый набор), сAggregateError, содержащим массив причин отклонения. -
Promise.race() - Принимает итерируемый набор промисов в качестве входных данных и возвращает один
Promise. Этот возвращаемый промис устанавливается в конечном состоянии первого установившегося промиса. -
Promise.reject() - Возвращает новый объект
Promise, который отклонен с указанной причиной. -
Promise.resolve() - Возвращает объект
Promise, который разрешен с указанным значением. Если значение является thenable (то есть имеет методthen), возвращаемый промис будет "следовать" за этим thenable, принимая его конечное состояние; в противном случае возвращаемый промис будет выполнен с указанным значением. -
Promise.try() - Принимает колбэк любого типа (возвращает или выбрасывает, синхронно или асинхронно) и разрешает его результат в
Promise. -
Promise.withResolvers() - Возвращает объект, содержащий новый объект
Promiseи две функции для его разрешения или отклонения, соответствующие двум параметрам, передаваемым исполнителю конструктораPromise().
Свойства экземпляра
Эти свойства определены на Promise.prototype и разделяются всеми экземплярами Promise.
-
Promise.prototype.constructor - Конструктор, который создал объект экземпляра. Для экземпляров
Promiseначальным значением является конструкторPromise. -
Promise.prototype[Symbol.toStringTag] - Начальным значением свойства
[Symbol.toStringTag]является строка"Promise". Это свойство используется вObject.prototype.toString().
Методы экземпляра
-
Promise.prototype.catch() - Добавляет обработчик отклонения к промису и возвращает новый промис, который разрешается значением возврата обработчика, если он был вызван, или исходным значением выполнения, если промис был вместо этого выполнен.
-
Promise.prototype.finally() - Добавляет обработчик к промису и возвращает новый промис, который разрешается, когда исходный промис разрешен. Обработчик вызывается, когда промис установлен, будь то выполнен или отклонен.
-
Promise.prototype.then() - Добавляет обработчики выполнения и отклонения к промису и возвращает новый промис, который разрешается значением возврата вызванного обработчика, или исходным установленным значением, если промис не был обработан (то есть, если соответствующий обработчик
onFulfilledилиonRejectedне является функцией).
Примеры
Базовый пример
В этом примере мы используем setTimeout(...) для имитации асинхронного кода. В действительности вы, вероятно, будете использовать что-то вроде XHR или HTML API.
const myFirstPromise = new Promise((resolve, reject) => {
// We call resolve(...) when what we were doing asynchronously
// was successful, and reject(...) when it failed.
setTimeout(() => {
resolve("Success!"); // Yay! Everything went well!
}, 250);
});
myFirstPromise.then((successMessage) => {
// successMessage is whatever we passed in the resolve(...) function above.
// It doesn't have to be a string, but if it is only a succeed message, it probably will be.
console.log(`Yay! ${successMessage}`);
});
Пример с различными ситуациями
Этот пример демонстрирует различные методы использования возможностей Promise и различные ситуации, которые могут возникнуть. Чтобы понять это, начните с прокрутки вниз блока кода и изучите цепочку промисов. После предоставления исходного промиса может следовать цепочка промисов. Цепочка состоит из вызовов .then() и обычно (но не обязательно) имеет единственный .catch() в конце, за которым опционально следует .finally(). В этом примере цепочка промисов инициируется пользовательским конструктом new Promise(); но на практике цепочки промисов чаще начинаются с API-функции (написанной кем-то другим), которая возвращает промис.
Пример функции tetheredGetNumber() показывает, что генератор промисов будет использовать reject() при настройке асинхронного вызова, или внутри колбэка, или обоих. Функция promiseGetWord() иллюстрирует, как API-функция может генерировать и возвращать промис в самодостаточном виде.
Обратите внимание, что функция troubleWithGetNumber() заканчивается throw. Это принудительно, потому что цепочка промисов проходит через все промисы .then(), даже после ошибки, и без throw ошибка казалась бы "исправленной". Это неудобно, и по этой причине принято опускать onRejected по всей цепочке промисов .then() и иметь только один onRejected в конечном catch().
Этот код можно запустить в Node.js. Понимание улучшается при фактическом наблюдении ошибок. Чтобы вызвать больше ошибок, измените значения threshold.
// To experiment with error handling, "threshold" values cause errors randomly
const THRESHOLD_A = 8; // can use zero 0 to guarantee error
function tetheredGetNumber(resolve, reject) {
setTimeout(() => {
const randomInt = Date.now();
const value = randomInt % 10;
if (value < THRESHOLD_A) {
resolve(value);
} else {
reject(new RangeError(`Too large: ${value}`));
}
}, 500);
}
function determineParity(value) {
const isOdd = value % 2 === 1;
return { value, isOdd };
}
function troubleWithGetNumber(reason) {
const err = new Error("Trouble getting number", { cause: reason });
console.error(err);
throw err;
}
function promiseGetWord(parityInfo) {
return new Promise((resolve, reject) => {
const { value, isOdd } = parityInfo;
if (value >= THRESHOLD_A - 1) {
reject(new RangeError(`Still too large: ${value}`));
} else {
parityInfo.wordEvenOdd = isOdd ? "odd" : "even";
resolve(parityInfo);
}
});
}
new Promise(tetheredGetNumber)
.then(determineParity, troubleWithGetNumber)
.then(promiseGetWord)
.then((info) => {
console.log(`Got: ${info.value}, ${info.wordEvenOdd}`);
return info;
})
.catch((reason) => {
if (reason.cause) {
console.error("Had previously handled error");
} else {
console.error(`Trouble with promiseGetWord(): ${reason}`);
}
})
.finally((info) => console.log("All done"));
Продвинутый пример
Этот небольшой пример показывает механизм Promise. Метод testPromise() вызывается каждый раз при нажатии на <button>. Он создает промис, который будет выполнен, используя setTimeout(), на счетчик промисов (число, начиная с 1) каждые 1-3 секунды, случайным образом. Конструктор Promise() используется для создания промиса.
Выполнение промиса регистрируется через колбэк выполнения, установленный с помощью p1.then(). Несколько записей в журнале показывают, как синхронная часть метода отделена от асинхронного завершения промиса.
Нажав кнопку несколько раз за короткое время, вы даже увидите, как разные промисы выполняются один за другим.
HTML
<button id="make-promise">Make a promise!</button> <div id="log"></div>
JavaScript
"use strict";
let promiseCount = 0;
function testPromise() {
const thisPromiseCount = ++promiseCount;
const log = document.getElementById("log");
// begin
log.insertAdjacentHTML("beforeend", `${thisPromiseCount}) Started<br>`);
// We make a new promise: we promise a numeric count of this promise,
// starting from 1 (after waiting 3s)
const p1 = new Promise((resolve, reject) => {
// The executor function is called with the ability
// to resolve or reject the promise
log.insertAdjacentHTML(
"beforeend",
`${thisPromiseCount}) Promise constructor<br>`,
);
// This is only an example to create asynchronism
setTimeout(
() => {
// We fulfill the promise
resolve(thisPromiseCount);
},
Math.random() * 2000 + 1000,
);
});
// We define what to do when the promise is resolved with the then() call,
// and what to do when the promise is rejected with the catch() call
p1.then((val) => {
// Log the fulfillment value
log.insertAdjacentHTML("beforeend", `${val}) Promise fulfilled<br>`);
}).catch((reason) => {
// Log the rejection reason
console.log(`Handle rejected promise (${reason}) here.`);
});
// end
log.insertAdjacentHTML("beforeend", `${thisPromiseCount}) Promise made<br>`);
}
const btn = document.getElementById("make-promise");
btn.addEventListener("click", testPromise);
Результат
Загрузка изображения с помощью XHR
Ниже приведен другой пример использования Promise и XMLHttpRequest для загрузки изображения. Каждый шаг комментируется и позволяет внимательно следить за архитектурой Promise и XHR.
<h1>Promise example</h1>
function imgLoad(url) {
// Create new promise with the Promise() constructor;
// This has as its argument a function with two parameters, resolve and reject
return new Promise((resolve, reject) => {
// XHR to load an image
const request = new XMLHttpRequest();
request.open("GET", url);
request.responseType = "blob";
// When the request loads, check whether it was successful
request.onload = () => {
if (request.status === 200) {
// If successful, resolve the promise by passing back the request response
resolve(request.response);
} else {
// If it fails, reject the promise with an error message
reject(
Error(
`Image didn't load successfully; error code: + ${request.statusText}`,
),
);
}
};
// Handle network errors
request.onerror = () => reject(new Error("There was a network error."));
// Send the request
request.send();
});
}
// Get a reference to the body element, and create a new image object
const body = document.querySelector("body");
const myImage = new Image();
const imgUrl =
"https://mdn.github.io/shared-assets/images/examples/round-balloon.png";
// Call the function with the URL we want to load, then chain the
// promise then() method with two callbacks
imgLoad(imgUrl).then(
(response) => {
// The first runs when the promise resolves, with the request.response
// specified within the resolve() method.
const imageURL = URL.createObjectURL(response);
myImage.src = imageURL;
body.appendChild(myImage);
},
(error) => {
// The second runs when the promise
// is rejected, and logs the Error specified with the reject() method.
console.log(error);
},
);
Отслеживание текущего объекта настроек
Объект настроек — это окружение, которое предоставляет дополнительную информацию при выполнении кода JavaScript. Это включает в себя realm и карту модулей, а также специфичную для HTML информацию, такую как origin. Текущий объект настроек отслеживается, чтобы гарантировать, что браузер знает, какой из них использовать для данного фрагмента пользовательского кода.
Чтобы лучше понять это, мы можем более подробно рассмотреть, как realm может быть проблемой. Realm можно примерно представить как глобальный объект. Уникальность realms заключается в том, что они содержат всю необходимую информацию для выполнения кода JavaScript. Это включает такие объекты, как Array и Error. Каждый объект настроек имеет свою "копию" этих объектов, и они не разделяются. Это может привести к неожиданному поведению в отношении промисов. Чтобы обойти это, мы отслеживаем так называемый текущий объект настроек. Он представляет информацию, специфичную для контекста пользовательского кода, отвечающего за определенный вызов функции.
Чтобы проиллюстрировать это дальше, мы можем взглянуть на то, как <iframe>, встраиваемый в документ, взаимодействует со своим хостом. Поскольку все веб-API осведомлены о текущем объекте настроек, следующее будет работать во всех браузерах:
<!doctype html> <iframe></iframe> <!-- we have a realm here --> <script> // we have a realm here as well const bound = frames[0].postMessage.bind(frames[0], "some data", "*"); // bound is a built-in function — there is no user // code on the stack, so which realm do we use? setTimeout(bound); // this still works, because we use the youngest // realm (the incumbent) on the stack </script>
Та же концепция применима и к промисам. Если мы немного изменим предыдущий пример, мы получим:
<!doctype html> <iframe></iframe> <!-- we have a realm here --> <script> // we have a realm here as well const bound = frames[0].postMessage.bind(frames[0], "some data", "*"); // bound is a built in function — there is no user // code on the stack — which realm do we use? Promise.resolve(undefined).then(bound); // this still works, because we use the youngest // realm (the incumbent) on the stack </script>
Если мы изменим это так, чтобы <iframe> в документе прослушивал post messages, мы сможем наблюдать эффект текущего объекта настроек:
<!-- y.html --> <!doctype html> <iframe src="x.html"></iframe> <script> const bound = frames[0].postMessage.bind(frames[0], "some data", "*"); Promise.resolve(undefined).then(bound); </script>
<!-- x.html -->
<!doctype html>
<script>
window.addEventListener("message", (event) => {
document.querySelector("#text").textContent = "hello";
// this code will only run in browsers that track the incumbent settings object
console.log(event);
});
</script>
В приведенном выше примере внутренний текст <iframe> будет обновлен только в том случае, если отслеживается текущий объект настроек. Это потому, что без отслеживания текущего объекта мы можем в конечном итоге использовать неправильное окружение для отправки сообщения.
Примечание: В настоящее время отслеживание текущего realm полностью реализовано в Firefox и имеет частичные реализации в Chrome и Safari.
Спецификации
Совместимость с браузерами
| Desktop | Мобильный | Сервер | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on iOS | Samsung Internet | WebView Android | WebView on iOS | Bun | Deno | Node.js | |
Promise |
32 |
12 |
29 |
19 |
19 |
32 |
29 |
19 |
8 |
2.0 |
4.4.3 |
8 |
1.0.0 |
1.0 |
0.12.0 |
@@species |
51 |
79 |
48 |
38 |
10 |
51 |
48 |
41 |
10 |
5.0 |
51 |
10 |
1.0.0 |
1.0 |
6.5.0 |
Promise |
32 |
12 |
29Конструктор требует оператор new начиная с версии 37. |
19 |
8Конструктор требует оператор new начиная с версии 10. |
32 |
29Конструктор требует оператор new начиная с версии 37. |
19 |
8Конструктор требует оператор new начиная с версии 10. |
2.0 |
4.4.3 |
8Конструктор требует оператор new начиная с версии 10. |
1.0.0 |
1.0 |
0.12.0Конструктор требует оператор new начиная с версии 4. |
all |
32 |
12 |
29 |
19 |
8 |
32 |
29 |
19 |
8 |
2.0 |
4.4.3 |
8 |
1.0.0 |
1.0 |
0.12.0 |
allKeyed |
Нет |
Нет |
155 |
Нет |
Нет |
Нет |
155 |
Нет |
Нет |
Нет |
Нет |
Нет |
? |
? |
? |
allSettled |
76 |
79 |
71 |
63 |
13 |
76 |
79 |
54 |
13 |
12.0 |
76 |
13 |
1.0.0 |
1.0 |
12.9.0 |
allSettledKeyed |
Нет |
Нет |
155 |
Нет |
Нет |
Нет |
155 |
Нет |
Нет |
Нет |
Нет |
Нет |
? |
? |
? |
any |
85 |
85 |
79 |
71 |
14 |
85 |
79 |
60 |
14 |
14.0 |
85 |
14 |
1.0.0 |
1.2 |
15.0.0 |
catch |
32 |
12 |
29 |
19 |
8 |
32 |
29 |
19 |
8 |
2.0 |
4.4.3 |
8 |
1.0.0 |
1.0 |
0.12.0 |
finally |
63 |
18 |
58 |
50 |
11.1 |
63 |
58 |
46 |
11.3 |
8.0 |
63 |
11.3 |
1.0.0 |
1.0 |
10.0.0 |
incumbent_settings_object_tracking |
Нет |
Нет |
50 |
Нет |
Нет |
Нет |
50 |
Нет |
Нет |
Нет |
Нет |
Нет |
? |
Нет |
Нет |
race |
32 |
12 |
29 |
19 |
8 |
32 |
29 |
19 |
8 |
2.0 |
4.4.3 |
8 |
1.0.0 |
1.0 |
0.12.0 |
reject |
32 |
12 |
29 |
19 |
8 |
32 |
29 |
19 |
8 |
2.0 |
4.4.3 |
8 |
1.0.0 |
1.0 |
0.12.0 |
resolve |
32 |
12 |
29 |
19 |
8 |
32 |
29 |
19 |
8 |
2.0 |
4.4.3 |
8 |
1.0.0 |
1.0 |
0.12.0 |
then |
32 |
12 |
29 |
19 |
8 |
32 |
29 |
19 |
8 |
2.0 |
4.4.3 |
8 |
1.0.0 |
1.0 |
0.12.0 |
try |
128 |
128 |
134 |
114 |
18.2 |
128 |
134 |
85 |
18.2 |
28.0 |
128 |
18.2 |
1.1.22 |
1.46 |
23.0.0 |
withResolvers |
119 |
119 |
121 |
105 |
17.4 |
119 |
121 |
79 |
17.4 |
25.0 |
119 |
17.4 |
1.0.0 |
1.38 |
22.0.0 |
См. также
- Polyfill
Promiseвcore-js - Руководство по использованию промисов
- Спецификация Promises/A+
- JavaScript Promises: an introduction на web.dev (2013)
- Callbacks, Promises, and Coroutines: Asynchronous Programming Patterns in JavaScript презентация Доменика ДеНиколы (2011)
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise