Полный цикл в digital

Функции Promise

Функции Promise.all(), Promise.allSettled(), Promise.race() позволяют сгруппировать выполнение нескольких промисов.

Функция Promise.all

Функция возвращает единый объект Promise, который объединяет набор промисов. Рассмотрим следуюший код:

const promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 1000, "Hello");
});
const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, "World");
});
// Hello
promise1.then((value) => console.log(value)); 
// World
promise2.then((value) => console.log(value));

Здесь определено два промиса, асинхронная операция первого промиса выполняется через 1000 миллисекунд, действие второго промиса выполняется через 500 миллисекунд. Оба этих промиса выполняются независимо друг от друга, консольный вывод:

World
Hello

Функция Promise.all() позволяет объединить несколько промисов и выполнять их параллельно, но как единое целое. В качестве параметра функция принимает набор промисов:

Promise.all([промис1, промис2, ... прромисN]);

Возвращаемым результатом функции является новый объект Promise.

Теперь изменим предыдущий пример, использовав функцию Promise.all():

const promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 1000, "Hello");
});
const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, "World");
});
Promise.all([promise1, promise2]).then((values) => {
  const [promise1data, promise2data] = values;
  console.log(promise1data, promise2data); // Hello World
});

Теперь данные обоих промисов возвращаются вместе и доступны в методе then() в виде массива values. Консольный вывод:

Hello World

Значения всех промисов возвращаются только если все они завершились успешно. Но если в асинхронной операции хотя бы одного промиса возникнет ошибка в силу внутренней логики или из-за вызова функции reject(), то все промисы перейдут в состояние rejected, соответственно:

const promise1 = new Promise((resolve, reject) => {
  reject("Непредвиденная ошибка");
  setTimeout(resolve, 500, "Hello");
});
const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 1000, "World");
});
Promise.all([promise1, promise2])
  .then((values) => {
    const [promise1data, promise2data] = values;
    console.log(promise1data, promise2data);
  })
  // непредвиденная ошибка
  .catch((error) => console.log(error));

В данном случае мы явным образом переводим переводим первый промис в состояние rejected, соответственно в это состояние переводятся все промисы, переданные в функцию Promise.all(). И далее через метод catch(), как и в обзем случае, мы можем обработать возникшую ошибку.

Promise.allSettled

Еще одна функция, также как и предыдущая принимает набор промисов и выполняет их как единое целое, но возвращает объект со статусом и результатом промиса:

const promise1 = new Promise((resolve, reject) => {
  reject("Непредвиденная ошибка");
  setTimeout(resolve, 500, "Hello");
});
const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 1000, "World");
});
Promise.allSettled([promise1, promise2]).then((values) => {
  const [promise1data, promise2data] = values;
  // {status: "rejected", reason: "Непредвиденная ошибка"}
  console.log(promise1data);
  // {status: "fulfilled", value: "World"}
  console.log(promise2data);
});

При этом при возникновении ошибки в одном из промисов (как в случае выше с первым промисом) функция также передается результаты в метод then(), который следует дальше в цепочке. Каждый результат представляет объект. Первое свойство этого объекта - status описывает статус или состояние промиса. Если произошла ошибка, статус rejected, второе свойство представляет объект ошибки. Если промис успешно завершил выполнение, то статус fulfilled, второе свойство - value хранит результат промиса.

Promise.race

Функция также принимает несколько промисов, только возвращает первый завершенный промис, вне зависимости завершился от успешно или с ошибкой:

const promise1 = new Promise((resolve) => {
  setTimeout(resolve, 500, "Hello");
});
const promise2 = new Promise((resolve) => {
  setTimeout(resolve, 1000, "World");
});
Promise.race([promise1, promise2])
  // Hello
  .then((value) => console.log(value))
  .catch((error) => console.log(error));

В данном случае первым выполненным будет промис promise1. Поэтому в метод then(value => console.log(value)) в качестве value будет передана строка Hello.

Promise.any

Функция принимает несколько промисов и возвращает первый успешно завершившийся промис:

const promise1 = new Promise((resolve, reject) => {
  reject("error in promise1");
  setTimeout(resolve, 500, "Hello");
});
const promise2 = new Promise((resolve) => {
  setTimeout(resolve, 1000, "World");
});
Promise.any([promise1, promise2])
  // World
  .then((value) => console.log(value))
  .catch((error) => console.log(error));

В данном случае первым выполненным будет промис promise1, однако он завершается с ошибкой. Поэтому в метод then(value => console.log(value)) в качестве value будет передана строка World - результат промиса promise2, который успешно завершается.

Может показаться, что Promise.any() делает то же самое, что и Promise.race(), однако эти функции отличаются в отношении того, как они работают с промисами, которые завершились с ошибкой. Promise.race() возвращает первый завершенный промис, вне зависимости завершился он с ошибкой или нет. А Promise.any() возвращает первый успешно завершенный промис, если такой имеется. Если же все промисы завершились с ошибкой, то генерируется исключение типа AggregateError:

const promise1 = new Promise((resolve, reject) => {
  reject("error in promise1");
  setTimeout(resolve, 500, "Hello");
});
const promise2 = new Promise((resolve, reject) => {
  reject("error in promise2");
  setTimeout(resolve, 1000, "World");
});
Promise.any([promise1, promise2])
  .then((value) => console.log(value))
  // AggregateError: All promises were rejected
  .catch((error) => console.log(error)); 

С помощью свойства errors типа AggregateError можно получить в виде массива все ошибки, которые возникли в промисах:

const promise1 = new Promise((resolve, reject) => {
  reject("error in promise1");
  setTimeout(resolve, 500, "Hello");
});
const promise2 = new Promise((resolve, reject) => {
  reject("error in promise2");
  setTimeout(resolve, 1000, "World");
});
Promise.any([promise1, promise2])
  .then((value) => console.log(value))
  // ["error in promise1", "error in promise2"]
  .catch((e) => console.log(e.errors));
Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!
Эйч Маркетинг