Promise

Об'єкт Promise (зобов'язання, проміс) відображає успішне (або невдале) завершення якоїсь асинхронної операції та значення її результату.

Щоб дізнатися більше про те, як працюють проміси і як їх застосовувати, краще спершу прочитати застосування промісів.

Опис

Promise – це заміна для значення, яке, як правило, невідоме на момент, коли проміс створюється. Він дає змогу прив'язати обробники до результату успішного виконання чи до причини невдачі асинхронної операції. Це дає асинхронним методам змогу повертати значення схоже до того, як це роблять синхронні функції. Замість повернути одразу кінцеве значення метод повертає promise - зобов'язання надати це значення в якийсь момент у майбутньому.

Promise завжди знаходиться в одному з таких станів:

  • Очікування — pending: початковий стан, ні сповнений, ні відхилений.
  • Сповнений — fulfilled: означає, що операція була успішно завершена.
  • Відхилений — rejected: означає, що операція завершилася невдало.

Кінцевий стан промісу, який знаходиться в стані очікування, може бути або сповнений якимось результатом, або відхилений з якоїсь причини (через помилку). Коли відбувається якийсь із цих варіантів, викликаються відповідні обробники, задані методом then промісу. Якщо проміс уже було сповнено чи відхилено на момент, коли приєднується відповідний обробник, цей обробник буде одразу викликано. Таким чином не трапляється стан гонитви між асинхронною операцією завершення і приєднанням її обробників.

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

Діаграма, що показує, як стан промісу змінюється між очікуванням, сповненістю та відхиленістю за допомогою обробників then/catch. Проміс в стані очікування може стати або сповненим, або відхиленим. Якщо він був сповнений, то виконується обробник "при сповненні", або ж перший параметр метода then(), і продовжуються подальші асинхронні дії. Якщо проміс був відхилений, то виконується обробник помилки, або переданий як другий параметр метода then(), або як єдиний параметр метода catch().

Також можна зустріти використання з промісами терміну вирішений, – це означає, що проміс залагоджений або "замкнений" на відповідність кінцевому стану іншого проміса, і подальше його вирішення чи відхилення буде безрезультатним. Документ Стани та долі (англ.) з оригінальної пропозиції промісів містить більше деталей щодо термінології промісів. У розмовній мові "вирішені" проміси нерідко еквівалентні до "сповнених", але, як це показано в "Станах та долях", вирішені проміси також можуть очікувати чи бути відхиленими. Наприклад:

new Promise((resolveOuter) => {
  resolveOuter(
    new Promise((resolveInner) => {
      setTimeout(resolveInner, 1000);
    }),
  );
});

Цей проміс є вже вирішеним на час створення (бо resolveOuter викликана синхронно), але він вирішений з іншим промісом, а тому не буде сповненим іще 1 секунду, поки не сповниться внутрішній проміс. На практиці "вирішення" нерідко виконується за лаштунками й не може відстежуватися, натомість сповнення й відхилення проміса – можуть.

Примітка: Декілька інших мов мають механізми лінивих та відкладених обчислень, котрі теж звуться "промісами", наприклад, Scheme. Проміси в JavaScript представляють процеси, що вже відбуваються, котрі можна зв'язати в ланцюжок за допомогою функцій зворотного виклику. Якщо треба ліниво обчислити вираз, слід розглянути можливість використання функції без аргументів, наприклад, f = () => expression, що породжує ліниво обчислений вираз, обчислити котрий можна за допомогою f().

Ланцюжки промісів

Методи Promise.prototype.then(), Promise.prototype.catch() і Promise.prototype.finally() використовуються, щоб приєднати якусь наступну дію до промісу, який залагоджується. Оскільки ці методи повертають проміси, їх виклики можна об'єднати в ланцюжок.

Метод .then() приймає до двох аргументів; перший — це функція зворотного виклику для сповнення промісу, а другий — відповідно, функція для його відхилення. Кожний .then() повертає новостворений об'єкт промісу, який далі може (необов'язково) використовуватися для нарощування ланцюжка викликів, як от:

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("foo");
  }, 300);
});

myPromise
  .then(handleFulfilledA, handleRejectedA)
  .then(handleFulfilledB, handleRejectedB)
  .then(handleFulfilledC, handleRejectedC);

Процес продовжується до наступної ланки ланцюжка, навіть якщо у наступний .then() не було передано функцію зворотного виклику. Таким чином, ланцюжок може спокійно оминати кожний виклик функції відхилення аж до останнього .catch().

Обробка відхиленого промісу в кожному .then() має наслідки далі всередині ланцюжка промісів. Інколи просто немає вибору, оскільки помилка має бути опрацьована одразу. В такому випадку ми повинні викинути помилку якогось типу, щоб зберегти вміст помилки далі всередині послідовності. З іншого боку, в разі відсутності нагальної потреби простіше віддати обробку помилки останній інструкції .catch() у ланцюжку. Фактично .catch() — це просто .then(), тільки без гнізда для функції успішного сповнення промісу.

myPromise
  .then(handleFulfilledA)
  .then(handleFulfilledB)
  .then(handleFulfilledC)
  .catch(handleRejectedAny);

Реалізація послідовності промісів, записана із застосуванням стрілкових функцій як функцій зворотного виклику, може мати якийсь такий вигляд:

myPromise
  .then((value) => {
    return value + " іще ланка";
  })
  .then((value) => {
    return value + " і знову ланка";
  })
  .then((value) => {
    return value + " і знову";
  })
  .then((value) => {
    return value + " і знову";
  })
  .then((value) => {
    console.log(value);
  })
  .catch((err) => {
    console.log(err);
  });

Примітка: Для швидшого виконання всі синхронні дії краще виконувати в межах одного обробника, інакше виконання всіх обробників у послідовності займе декілька тактів.

Стан, з яким завершується проміс, визначає результат, яким "залагоджується" наступний проміс у послідовності. "Сповнений" стан позначає успішне завершення промісу, а стан "відхилено" — невдачу. Результат, повернутий кожним сповненим промісом у послідовності, передається далі до наступного .then(), натомість причина, з якої було відхилено якийсь із промісів, передається тільки до наступного обробника помилки у послідовності.

Проміси в послідовності – вкладені один в одного, проте вони знімаються подібно до елементів стека. Перший проміс у послідовності загорнутий найглибше, проте він же буде першим, що витягнуть.

(проміс D, (проміс C, (проміс B, (проміс A) ) ) )

Якщо наступне значення nextValue — проміс, працює ефект динамічної заміни. Інструкція return змушує витягнути проміс зі стека, проте на його місце одразу вкладається проміс nextValue. У випадку, наведеному вище, припустімо, що .then(), пов'язаний з "промісом B", поверне "проміс X" як nextValue. Після цього картина вкладення матиме такий вигляд:

(проміс D, (проміс C, (проміс X) ) )

Один і той самий проміс може бути вкладений в декілька різних промісів. В прикладі нижче перехід promiseA в "залагоджений" стан змусить спрацювати обидва .then().

const promiseA = new Promise(myExecutorFunc);
const promiseB = promiseA.then(handleFulfilled1, handleRejected1);
const promiseC = promiseA.then(handleFulfilled2, handleRejected2);

Можна прив'язати якусь дію до вже "залагодженого" промісу. В цьому випадку дію (якщо це допустимо) буде виконано при першій ліпшій асинхронній можливості. Зауважте, що проміси гарантовано асинхронні. Таким чином, дія для уже "залагодженого" промісу трапиться лише після того, як стек викликів буде очищено і мине мить таймера рушія. Цей ефект дуже схожий до результату виконання setTimeout(action, 0).

const promiseA = new Promise((resolve, reject) => {
  resolve(777);
});
// В цей момент "promiseA" уже залагоджено.
promiseA.then((val) =>
  console.log("асинхронний запис із таким значенням:", val),
);
console.log("запис одразу");

// виводить результати в такому порядку:
// запис одразу
// асинхронний запис із таким значенням: 777

Очікувані

Екосистема JavaScript мала декілька реалізацій промісів задовго до того, як вони стали частиною мови. Бувши всередині представленими по-різному, всі промісоподібні об'єкти щонайменше реалізовували інтерфейс очікуваного (thenables). Очікуваний об'єкт реалізовує метод .then(), котрий викликається з двома функціями зворотного виклику: одною на випадок сповнення промісу, однак на випадок відхилення. Проміси так само є очікуваними.

Щоб взаємодіяти з наявними реалізаціями Promise, мова дозволяє використання очікуваних об'єктів замість промісів. Наприклад, Promise.resolve вирішить не лише проміси, а й відстежить очікувані.

const aThenable = {
  then(onFulfilled, onRejected) {
    onFulfilled({
      // Очікуваний сповнюється іншим очікуваним
      then(onFulfilled, onRejected) {
        onFulfilled(42);
      },
    });
  },
};
Promise.resolve(aThenable); // Проміс сповнюється значенням 42

Рівночасність промісів

Клас Promise пропонує чотири методи для спрощення реалізації рівночасності асинхронних задач:

Promise.all()

Сповнюється, коли сповнюються всі проміси; відхиляється, коли відхиляється будь-який з промісів.

Promise.allSettled()

Сповнюється, коли залагоджуються всі проміси.

Promise.any()

Сповнюється, коли сповнюється будь-який з промісів; відхиляється, коли відхиляються всі проміси.

Promise.race()

Залагоджується, коли залагоджується будь-який з промісів. Інакше кажучи, сповнюється, коли сповнюється будь-який з промісів; відхиляється, коли відхиляється будь-який з промісів.

Усі ці методи приймають ітеровані колекції промісів (очікуваних, якщо точніше) і повертають новий проміс. Усі вони підтримують підкласи, а отже – їх можна викликати на підкласах Promise, а результат буде промісом з типом підкласу. Для цього конструктор підкласу мусить реалізувати таку само сигнатуру, як конструктор Promise(): приймання єдиної функції executor, що може бути викликана з функціями зворотного виклику resolve і reject як параметрами. Підклас також мусить мати статичний метод resolve, котрий можна викликати як Promise.resolve() для загортання значень у проміси.

Зверніть увагу, що JavaScript за своєю природою є однопотоковою мовою, тож у конкретну мить може виконуватися лише одна задача, хоч контроль може переходити від одного промісу до іншого, через що проміси здаються рівночасними. Паралельне виконання у JavaScript може бути досягнуто лише за допомогою тредів-воркерів.

Конструктор

Promise()

Створює новий об'єкт типу Promise. Здебільшого застосовується, щоб обгорнути функцію, яка ще не підтримує проміси.

Статичні властивості

Promise[@@species]

Повертає конструктор, що використовується для створення значень, повернених з методів промісів.

Статичні методи

Promise.all()

Приймає на вхід ітеровану колекцію промісів і повертає єдиний Promise. Цей повернений проміс сповнюється, коли сповнюються всі проміси з вихідної колекції (включно з випадком, коли передана колекція – порожня), причому сповнюється масивом значень сповнення окремих промісів. Він відхиляється, коли відхиляється будь-який з промісів з вихідної колекції, причому значенням відхилення стає причина цього першого відхилення.

Promise.allSettled()

Приймає на вхід ітеровану колекцію промісів і повертає єдиний Promise. Цей повернений проміс сповнюється, коли залагоджуються всі проміси з вихідної колекції (включно з випадком, коли передана колекція – порожня), причому сповнюється масивом об'єктів, що описують результати кожного промісу.

Promise.any()

Приймає на вхід ітеровану колекцію промісів і повертає єдиний Promise. Цей повернений проміс сповнюється, коли сповнюється будь-який з промісів з вихідної колекції, причому сповнюється значенням сповнення цього першого сповненого промісу. Він відхиляється, коли відхиляються всі проміси з вихідної колекції (включно з випадком, коли передана колекція – порожня), причому значенням відхилення стає об'єкт AggregateError, що містить масив причин відхилення.

Promise.race()

Приймає на вхід ітеровану колекцію промісів і повертає єдиний Promise. Цей повернений проміс залагоджується зі станом, що відповідає остаточному станові першого промісу, що залагодився.

Promise.reject()

Повертає новий об'єкт типу Promise, який відхиляється з переданою причиною.

Promise.resolve()

Повертає об'єкт типу Promise, який вирішується з переданим результатом. Якщо результат є then-спроможним (має метод then - "відтак"), то повернений в результаті проміс "прослідкує" за цим then-спроможним і прийме його кінцевий стан. Інакше цей проміс буде просто сповнено переданим значенням.

Promise.withResolvers()

Повертає об'єкт, що вміщає новий об'єкт Promise і дві функції для його розв'язання чи відхилення, що відповідають двом параметрам, переданим до виконувача конструктора Promise().

Властивості примірника

Ці властивості означені на Promise.prototype і є спільними для всіх примірників Promise.

Promise.prototype.constructor

Функція-конструктор, що створила об'єкт-примірник. Для примірників Promise початковим значенням є конструктор Promise.

Promise.prototype[@@toStringTag]

Початкове значення властивості @@toStringTag – рядок "Promise". Ця властивість використовується в Object.prototype.toString().

Методи примірника

Promise.prototype.catch() (перехопити)

Додає до промісу обробник відхилення і повертає новий проміс, який вирішується або з результатом виконання переданої функції зворотного виклику, або — якщо початковий проміс сповнився — значенням сповнення початкового проміса.

Promise.prototype.finally() (зрештою)

Додає до промісу обробник і повертає новий проміс, який вирішується, якщо початковий проміс теж вирішується. Обробник викликається, коли проміс залагоджується, незалежно від того, чи його було сповнено, чи відхилено.

Promise.prototype.then() (відтак)

Додає до промісу обробники виконання і відхилення, і повертає новий проміс. Цей новий проміс або залагоджується з результатом виклику відповідного обробника, або повертає значення, з яким було залагоджено попередній проміс (в разі, якщо відповідний обробник — onFulfilled або onRejected — не є функцією).

Приклади

Базовий приклад

const myFirstPromise = new Promise((resolve, reject) => {
  // Викликаємо resolve(...), коли те, що ми робимо асинхронно, завершилося успіхом, і reject(...), якщо операція була невдалою.
  // В цьому прикладі використаємо setTimeout(...) для симуляції асинхронного коду.
  // На практиці тут буде щось схоже на XHR чи API HTML.
  setTimeout(() => {
    resolve("Успіх!"); // Ура! Все пройшло добре!
  }, 250);
});

myFirstPromise.then((successMessage) => {
  // successMessage — це будь-яке значення, яке ми передаємо в функцію resolve(...) вище.
  // Воно не зобов'язане бути рядком, проте якщо це просто повідомлення про успіх — воно, ймовірно, буде рядком.
  console.log(`Ура! ${successMessage}`);
});

Приклад із різноманітними ситуаціями

Цей приклад показує різноманітні техніки застосування можливостей промісів і різні ситуації, які можуть трапитись. Для розуміння цього прикладу прокрутіть до кінця блоку з кодом і перегляньте ланцюжок промісів. Після початкового проміса може бути ланцюжок промісів. Він складається із викликів .then(), і зазвичай (проте на завжди) має єдиний .catch() наприкінці, після якого інколи може викликатись .finally(). В цьому прикладі ланцюжок промісів ініційовано за допомогою самописного new Promise(), проте на практиці послідовність промісів зазвичай починається викликом функції API (написаної кимось іншим), яка повертає проміс.

Функція tetheredGetNumber() в прикладі зображає генератор промісу, який викличе reject() або під час влаштування асинхронного виклику, або всередині функції зворотного виклику, або ж і там, і там. Функція promiseGetWord() ілюструє, як функція API може створювати та повертати проміс автономно.

Зауважте, що функція troubleWithGetNumber() завершується throw. Це вимушений крок, оскільки послідовність промісів у ES6 проходить через всі .then(), навіть після помилки. І без цього throw помилка буде здаватися "виправленою". Це зайвий клопіт, і через це зазвичай опускають onRejected у всій послідовності промісів .then() і просто залишають єдину onRejected всередині кінцевого catch().

Цей код може запускатися в середовищі NodeJS. Він буде більш зрозумілим, якщо переглянути помилки, які виникнуть у процесі виконання. Щоб збільшити кількість помилок, змініть значення threshold.

// Для експерименту з обробкою помилок значення "threshold" приводять до помилок випадковим чином
const THRESHOLD_A = 8; // можна використати 0, щоб гарантувати помилку

function tetheredGetNumber(resolve, reject) {
  setTimeout(() => {
    const randomInt = Date.now();
    const value = randomInt % 10;
    if (value < THRESHOLD_A) {
      resolve(value);
    } else {
      reject(`Завелике значення: ${value}`);
    }
  }, 500);
}
function determineParity(value) {
  const isOdd = value % 2 === 1;
  return { value, isOdd };
}

function troubleWithGetNumber(reason) {
  const err = new Error("Проблема з отриманням числа", { 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(`Все ж завелике значення: ${value}`);
    } else {
      parityInfo.wordEvenOdd = isOdd ? "odd" : "even";
      resolve(parityInfo);
    }
  });
}

new Promise(tetheredGetNumber)
  .then(determineParity, troubleWithGetNumber)
  .then(promiseGetWord)
  .then((info) => {
    console.log(`Отримано: ${info.value}, ${info.wordEvenOdd}`);
    return info;
  })
  .catch((reason) => {
    if (reason.cause) {
      console.error("Маємо помилку, оброблену раніше");
    } else {
      console.error(`Проблема з promiseGetWord(): ${reason}`);
    }
  })
  .finally((info) => console.log("Все зроблено"));

Поглиблений приклад

Цей невеличкий приклад ілюструє сам механізм промісу. Метод testPromise() викликається під час кожного натискання елементу <button>. Це створює проміс, який буде виконано за допомогою setTimeout(), зі значенням кількості промісів (число, починаючи з 1) кожні 1-3 секунди (інтервал випадковий). Для створення промісів використано конструктор Promise().

Виконання промісів записується через функцію зворотного виклику, задану всередині p1.then(). Декілька записів, які виводяться в процесі роботи програми, показують, як синхронна частина методу відділена від асинхронного завершення промісу.

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

HTML

<button id="make-promise">Створити проміс!</button>
<div id="log"></div>

JavaScript

"use strict";
let promiseCount = 0;

function testPromise() {
  const thisPromiseCount = ++promiseCount;
  const log = document.getElementById("log");
  // початок
  log.insertAdjacentHTML("beforeend", `${thisPromiseCount}) Почалося<br>`);
  // Створюємо новий проміс: ми зобов'язуємося надати числовий лічильник цього промісу,
  // що починається з 1 (після очікування протягом 3 секунд)
  const p1 = new Promise((resolve, reject) => {
    // Функція, яка працює над виконанням промісу, викликається з можливістю
    // або вирішити, або відхилити проміс
    log.insertAdjacentHTML(
      "beforeend",
      `${thisPromiseCount}) Конструктор промісу<br>`,
    );
    // Це лише приклад того, як може виникнути асинхронність
    setTimeout(
      () => {
        // Сповнюємо проміс
        resolve(thisPromiseCount);
      },
      Math.random() * 2000 + 1000,
    );
  });

  // Оголошуємо через виклик then(), що саме потрібно зробити, коли проміс вирішується,
  // а за допомогою виклику catch() — що робити, якщо проміс відхилено
  p1.then((val) => {
    // Виводимо значення, яким сповнився проміс
    log.insertAdjacentHTML("beforeend", `${val}) Проміс сповнено<br>`);
  }).catch((reason) => {
    // Виводимо причину відхилення промісу
    console.log(`Тут оброблено відхилений проміс (${reason}).`);
  });
  // кінець
  log.insertAdjacentHTML(
    "beforeend",
    `${thisPromiseCount}) Проміс виконано<br>`,
  );
}

const btn = document.getElementById("make-promise");
btn.addEventListener("click", testPromise);

Результат

Завантаження зображення за допомогою XHR

Ще один простий приклад використання Promise, цього разу з завантаженням зображення за допомогою XMLHttpRequest, доступний на GitHub-репозиторії MDN js-examples. Також можна побачити його в дії. Кожний крок прокоментовано, що дає змогу докладно розглянути архітектуру промісів та XHR.

Відстежування поточного установчого об'єкта

Установчий об'єкт — це оточення, яке надає додаткову інформацію під час роботи JavaScript-коду. До нього входять царина (realm), карта модулів, а також специфічна для HTML інформація, наприклад, походження. Поточний установчий об'єкт постійно відстежується для гарантування того, що браузер знає, який із них застосовувати для даної ділянки користувацького коду.

Щоб краще це уявити, погляньмо ближче на те, яким чином царина може стати проблемою. Царину можна згрубша уявляти як глобальний об'єкт. Що особливого в царинах — так це те, що вони містять всю необхідну інформацію для виконання JavaScript-коду. Зокрема глобальні об'єкти, такі як Array та Error. Кожний установчий об'єкт має свою власну "копію" цих даних, і цю копію ні з ким не поділяє. Це може призвести до певної неочікуваної поведінки під час роботи з промісами. Щоб обійти такі проблеми, ми відстежуємо таку річ, як поточний установчий об'єкт. Він відповідає за інформацію, яка стосується контексту користувацького коду, відповідального за виклик певної функції.

Щоб краще це проілюструвати, подивімось на те, як вбудований в документ <iframe> спілкується зі своїм хазяїном. Оскільки всі веб-API мають на увазі поточний установчий об'єкт, наступний код буде працювати в усіх браузерах:

<!doctype html>
<!-- окрема царина в iframe -->
<iframe></iframe>
<script>
  // і також окрема царина тут
  const bound = frames[0].postMessage.bind(frames[0], "some data", "*");
  // bound – вбудована функція, тобто тут немає
  // користувацького коду на стеку, тож яка царина використовується?
  setTimeout(bound);
  // це все ж працює, оскільки ми використовуємо наймолодшу
  // царину (поточну) на стеку
</script>

Та сама ідея, але застосована до промісів. Якщо трошки змінити приклад вище, вийде отаке:

<!doctype html>
<!-- окрема царина в iframe -->
<iframe></iframe>
<script>
  // і також окрема царина тут
  const bound = frames[0].postMessage.bind(frames[0], "some data", "*");
  // bound – вбудована функція, тобто тут немає
  // користувацького коду на стеку, тож яка царина використовується?
  Promise.resolve(undefined).then(bound);
  // це все ж працює, оскільки ми використовуємо наймолодшу
  // царину (поточну) на стеку
</script>

Якщо змінити це таким чином, що <iframe> в документі слухатиме повідомлення, можна спостерігати ефект поточного установчого об'єкта:

<!-- 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";
      // Цей код спрацює лише у браузерах, які відстежують поточний установчий об'єкт
      console.log(event);
    },
    false,
  );
</script>

У наведеному вище прикладі текстовий вміст <iframe> буде оновлено лише у тому випадку, якщо поточний установчий об'єкт справді відстежується. Причина цього в тому, що без такого відстеження може трапитися надсилання повідомлення за допомогою не того середовища.

Примітка: Наразі відстежування поточної царини повністю реалізовано у Firefox і частково – в Chrome і Safari.

Специфікації

Сумісність із браузерами

desktop mobile server
Chrome Edge Firefox Internet Explorer Opera Safari WebView Android Chrome Android Firefox for Android Opera Android Safari on iOS Samsung Internet Deno Node.js
Promise
Chrome Full support 32
Edge Full support 12
Firefox Full support 29
Internet Explorer No support No
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
Promise() constructor Chrome Full support 32
Edge Full support 12
Firefox Full support 29
footnote
Internet Explorer No support No
Opera Full support 19
Safari Full support 8
footnote
WebView Android Full support 4.4.3
Chrome Android Full support 32
Firefox for Android Full support 29
footnote
Opera Android Full support 19
Safari on iOS Full support 8
footnote
Samsung Internet Full support 2.0
Deno Full support 1.0
Node.js Full support 0.12.0
footnote
all() Chrome Full support 32
Edge Full support 12
Firefox Full support 29
Internet Explorer No support No
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
allSettled() Chrome Full support 76
Edge Full support 79
Firefox Full support 71
Internet Explorer No support No
Opera Full support 63
Safari Full support 13
WebView Android Full support 76
Chrome Android Full support 76
Firefox for Android Full support 79
Opera Android Full support 54
Safari on iOS Full support 13
Samsung Internet Full support 12.0
Deno Full support 1.0
Node.js Full support 12.9.0
any Chrome Full support 85
Edge Full support 85
Firefox Full support 79
Internet Explorer No support No
Opera Full support 71
Safari Full support 14
WebView Android Full support 85
Chrome Android Full support 85
Firefox for Android Full support 79
Opera Android Full support 60
Safari on iOS Full support 14
Samsung Internet Full support 14.0
Deno Full support 1.2
Node.js Full support 15.0.0
catch() Chrome Full support 32
Edge Full support 12
Firefox Full support 29
Internet Explorer No support No
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
finally() Chrome Full support 63
Edge Full support 18
Firefox Full support 58
Internet Explorer No support No
Opera Full support 50
Safari Full support 11.1
WebView Android Full support 63
Chrome Android Full support 63
Firefox for Android Full support 58
Opera Android Full support 46
Safari on iOS Full support 11.3
Samsung Internet Full support 8.0
Deno Full support 1.0
Node.js Full support 10.0.0
Incumbent settings object tracking Chrome No support No
Edge No support No
Firefox Full support 50
Internet Explorer No support No
Opera No support No
Safari No support No
WebView Android No support No
Chrome Android No support No
Firefox for Android Full support 50
Opera Android No support No
Safari on iOS No support No
Samsung Internet No support No
Deno No support No
Node.js No support No
race() Chrome Full support 32
Edge Full support 12
Firefox Full support 29
Internet Explorer No support No
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
reject() Chrome Full support 32
Edge Full support 12
Firefox Full support 29
Internet Explorer No support No
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
resolve() Chrome Full support 32
Edge Full support 12
Firefox Full support 29
Internet Explorer No support No
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
then() Chrome Full support 32
Edge Full support 12
Firefox Full support 29
Internet Explorer No support No
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

Дивіться також