Promise.resolve()
Статичний метод Promise.resolve()
(вирішити, розв'язати) "вирішує" дане значення до об'єкта Promise
. Якщо це значення саме є промісом, то повертається цей проміс; якщо значення є очікуваним, то Promise.resolve()
викличе метод then()
з двома підготованими ним функціями зворотного виклику; інакше – повернений проміс буде сповнений переданим значенням.
Ця функція сплющує вкладені шари промісоподібних об'єктів (наприклад, проміс, що сповнюється промісом, котрий сповнюється чимось іще) до єдиного шару – проміс, котрий сповнюється значенням, котре не є очікуваним.
Спробуйте його в дії
Синтаксис
Promise.resolve(value)
Параметри
value
Аргумент, котрим буде вирішено цей
Promise
. Також може бути об'єктомPromise
, або очікуваним об'єктом, значення котрого буде застосовано для вирішення.
Повернене значення
Об'єкт Promise
, котрий вирішується переданим значенням, або проміс, котрий передали як значення, якщо це значення було об'єктом-промісом. Вирішений проміс може мати будь-який зі станів: сповнений, відхилений або очікування. Наприклад, вирішення відхиленим промісом все одно дасть відхилений проміс.
Опис
Promise.resolve()
вирішує проміс, що не те саме, що сповнення або відхилення промісу. Визначення термінології – в описі Promise. Якщо стисло, то Promise.resolve()
повертає проміс, чий кінцевий стан залежить від іншого промісу, очікуваного об'єкта або іще якогось значення.
[!NOTE] Якщо обчислення виразу
value
може викинути синхронну помилку, тоPromise.resolve()
не перехопить цю помилку та не загорне її у відхилений проміс. За таких умов розгляньте варіант використанняPromise.try(() => value)
.
Promise.resolve()
є узагальненим і підтримує підкласи, а отже – його можна викликати на підкласах Promise
, і результат буде промісом типу підкласу. Щоб це уможливити, конструктор підкласу мусить реалізувати таку ж сигнатуру, як конструктор Promise()
: приймання єдиної функції executor
, котра може бути викликана з функціями зворотного виклику resolve
і reject
як параметрами.
Promise.resolve()
має особливу логіку для обробки примірників Promise
. Коли value
належить до класу Promise
або його підкласу, і value.constructor === Promise
, то Promise.resolve()
безпосередньо повертає value
, не створюючи новий примірник Promise
. У решті випадків Promise.resolve()
по суті є скороченням для new Promise((resolve) => resolve(value))
.
Основна частина логіки вирішення насправді реалізована в функції resolve
, переданій конструктором Promise()
. У підсумку:
- Якщо передається значення, котре не є очікуваним об'єктом, то повернений проміс зразу сповнюється цим значенням.
- Якщо передається очікуваний об'єкт, то повернений проміс приймає стан цього очікуваного, викликаючи метод
then
та передаючи пару функцій вирішення як аргументи. (Однак через те, що нативні проміси проходять крізьPromise.resolve()
без змін, без утворення обгортки, то методthen
на нативних промісах не викликається.) Якщо функціяresolve
отримує іще один очікуваний об'єкт, то він так само вирішується, тож остаточне значення сповнення промісу ніколи не буде очікуваним об'єктом.
Приклади
Застосування статичного методу Promise.resolve
Promise.resolve("Успіх").then(
(value) => {
console.log(value); // "Успіх"
},
(reason) => {
// не викликається
},
);
Вирішення масивом
const p = Promise.resolve([1, 2, 3]);
p.then((v) => {
console.log(v[0]); // 1
});
Вирішення іншим промісом
Promise.resolve()
повторно використовує наявні примірники Promise
. Коли він вирішується нативним промісом, то повертає той самий примірник промісу, не створюючи обгортки.
const original = Promise.resolve(33);
const cast = Promise.resolve(original);
cast.then((value) => {
console.log(`значення: ${value}`);
});
console.log(`original === cast ? ${original === cast}`);
// По порядку виводить:
// original === cast ? true
// значення: 33
Зворотний порядок журналювання спричинений фактом того, що обробники then
викликаються асинхронно. Більше про це – на довідковій сторінці then()
.
Вирішення очікуваними об'єктами та викидання Error
// Вирішення очікуваним об'єктом
const p1 = Promise.resolve({
then(onFulfill, onReject) {
onFulfill("сповнено!!");
},
});
console.log(p1 instanceof Promise); // true, об'єкт приводиться до Promise
p1.then(
(v) => {
console.log(v); // "сповнено!"
},
(e) => {
// не викликається
},
);
// Очікуваний об'єкт викидає помилку
// Проміс відхиляється
const p2 = Promise.resolve({
then() {
throw new TypeError("Викидаємо");
},
});
p2.then(
(v) => {
// не викликається
},
(e) => {
console.error(e); // TypeError: Викидаємо
},
);
// Очікуваний об'єкт викидає помилку після зворотного виклику
// Проміс вирішується
const p3 = Promise.resolve({
then(onFulfilled) {
onFulfilled("Вирішуємо");
throw new TypeError("Викидаємо");
},
});
const p3 = Promise.resolve(thenable);
p3.then(
(v) => {
console.log(v); // "Вирішуємо"
},
(e) => {
// не викликається
},
);
Вкладені очікувані об'єкти "глибоко сплющуються" до єдиного промісу.
const thenable = {
then(onFulfilled, onRejected) {
onFulfilled({
// Цей очікуваний сповнюється іншим очікуваним
then(onFulfilled, onRejected) {
onFulfilled(42);
},
});
},
};
Promise.resolve(thenable).then((v) => {
console.log(v); // 42
});
[!WARNING] Не слід викликати
Promise.resolve()
на очікуваному об'єкті, що вміщає самого себе як значення вирішення. Це призводить до нескінченної рекурсії, адже намагається сплощити проміс нескінченної вкладеності.
const thenable = {
then(onFulfilled, onRejected) {
onFulfilled(thenable);
},
};
Promise.resolve(thenable); // Призведе до нескінченної рекурсії
Виклик resolve() на конструкторі, що не є Promise
Promise.resolve()
є узагальненим методом. Він може викликатися на будь-якому конструкторі, що реалізовує таку ж сигнатуру, як конструктор Promise()
. Наприклад, можна викликати його на конструкторі, що передає console.log
як resolve
:
class NotPromise {
constructor(executor) {
// Функції "resolve" і "reject" і близько не поводяться як аналоги
// в нативних промісів, але Promise.resolve() усе одно їх викликає.
executor(
(value) => console.log("Вирішено", value),
(reason) => console.log("Відхилено", reason),
);
}
}
Promise.resolve.call(NotPromise, "гов"); // Виводить "Вирішено гов"
Спроможність сплющувати вкладені очікувані об'єкти реалізована функцією resolve
конструктора Promise()
, тож якщо викликати метод Promise.resolve()
на іншому конструкторі, то вкладені очікувані можуть не сплющуватися, залежно від того, як такий конструктор реалізовує свою функцію resolve
.
const thenable = {
then(onFulfilled, onRejected) {
onFulfilled({
// Очікуваний сповнюється іншим очікуваним
then(onFulfilled, onRejected) {
onFulfilled(42);
},
});
},
};
Promise.resolve.call(NotPromise, thenable); // Виводить "Вирішено { then: [Function: then] }"
Специфікації
Сумісність із браузерами
desktop | mobile | server | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
resolve()
|
Chrome Full support 32 | Edge Full support 12 | Firefox Full support 29 | Internet Explorer No support Ні | Opera Full support 19 | Safari Full support 8 | WebView Android Full support 4.4.3 | Chrome Android Full support 32 | Firefox for Android Full support 29 | Opera Android Full support 19 | Safari on iOS Full support 8 | Samsung Internet Full support 2.0 | Deno Full support 1.0 | Node.js Full support 0.12.0 |