Промисы — важная функция современного JavaScript, которая позволяет разработчикам обрабатывать асинхронные операции более эффективным и удобочитаемым способом. В этом блоге мы углубимся в мир промисов и рассмотрим некоторые передовые методы работы с ними в JavaScript.

Что такое обещания?

Промисы — это объекты в JavaScript, которые представляют возможное завершение или сбой асинхронной операции и позволяют вам обрабатывать результат этой операции, когда он будет готов. Обещания имеют три состояния:

  • Ожидание: начальное состояние промиса при его создании.
  • Выполнено: состояние обещания при успешном завершении асинхронной операции.
  • Отклонено: состояние обещания при сбое асинхронной операции.

Промисы позволяют объединять асинхронные операции и обрабатывать ошибки более организованным способом, чем обратные вызовы.

Вот пример того, как создать и использовать промис в JavaScript:

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    const randomValue = Math.random();
    if (randomValue > 0.5) {
      resolve(randomValue);
    } else {
      reject(new Error('Random value is too low!'));
    }
  }, 1000);
});

myPromise.then((result) => {
  console.log(`Promise was fulfilled with result: ${result}`);
}).catch((error) => {
  console.error(`Promise was rejected with error: ${error}`);
});

В этом примере мы создаем новый объект Promise, который принимает функцию в качестве аргумента. Функция получает два параметра, resolve и reject, которые являются функциями, которые можно использовать для выполнения или отклонения обещания после завершения асинхронной операции.

В этом случае мы используем setTimeout для имитации асинхронной операции, выполнение которой занимает одну секунду. Мы генерируем случайное число, и если оно больше 0,5, мы выполняем обещание с этим значением. В противном случае мы отклоняем обещание с объектом ошибки.

Затем мы используем метод then для обработки выполнения обещания, записывая результат в консоль. Если обещание отклонено, мы обрабатываем ошибку с помощью метода catch.

Цепочка обещаний

Обещания также могут быть объединены в цепочку для выполнения ряда асинхронных операций. Это можно сделать, вернув новый Promise из метода then.

Вот пример того, как связать промисы в JavaScript:

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(10);
  }, 1000);
});

myPromise.then((result) => {
  console.log(`First result: ${result}`);
  return result * 2;
}).then((result) => {
  console.log(`Second result: ${result}`);
  return result - 4;
}).then((result) => {
  console.log(`Third result: ${result}`);
}).catch((error) => {
  console.error(`Promise was rejected with error: ${error}`);
});

В этом примере мы создаем новое обещание, которое выполняется через одну секунду со значением 10. Затем мы используем метод then, чтобы выполнить три операции над этим значением: удвоить его, вычесть 4 и записать окончательный результат в консоль.

Если какой-либо из методов then выдает ошибку, будет вызван метод catch с объектом ошибки.

Продвинутые методы обещаний

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

Обещание.гонка

Метод Promise.race похож на Promise.all, но вместо ожидания завершения всех промисов он ожидает выполнения или отклонения первого промиса. Метод принимает массив обещаний в качестве аргумента и возвращает новое обещание, которое выполняется с результатом первого выполненного обещания.

const promises = [
  new Promise((resolve) => setTimeout(() => resolve(1), 1000)),
  new Promise((resolve) => setTimeout(() => resolve(2), 500)),
  new Promise((resolve) => setTimeout(() => resolve(3), 2000)),
];

Promise.race(promises).then((result) => {
  console.log(`The first promise to complete returned ${result}`);
});

В этом примере мы создаем массив из трех обещаний, каждое из которых выполняется через разное время. Затем мы используем Promise.race, чтобы дождаться завершения первого промиса и записать его результат в консоль.

Обещание.все

Метод Promise.all принимает в качестве аргумента массив обещаний и возвращает новое обещание, которое выполняется с массивом результатов, когда все входные обещания выполнены, или отклоняет с указанием причины отклонения первого обещания.

const promises = [
  new Promise((resolve) => setTimeout(() => resolve(1), 1000)),
  new Promise((resolve) => setTimeout(() => resolve(2), 2000)),
  new Promise((resolve) => setTimeout(() => resolve(3), 3000)),
];

Promise.all(promises).then((values) => {
  console.log(`All promises resolved: ${values}`);
});

В этом примере мы создаем массив из трех обещаний, каждое из которых выполняется через разное время. Затем мы используем Promise.all, чтобы дождаться завершения всех промисов и записать их результаты в консоль.

Обещание.любое

Метод Promise.any похож на Promise.race, но вместо ожидания выполнения первого обещания он ожидает выполнения первого обещания. Если все промисы отклонены, метод выдает AggregateError, содержащий все причины отклонения.

const promises = [
  new Promise((resolve) => setTimeout(() => resolve(1), 1000)),
  new Promise((resolve, reject) => setTimeout(() => reject(new Error('Failed')), 500)),
  new Promise((resolve) => setTimeout(() => resolve(3), 2000)),
];

Promise.any(promises).then((result) => {
  console.log(`The first promise to fulfill returned ${result}`);
}).catch((error) => {
  console.error(`All promises were rejected: ${error}`);
});

В этом примере мы создаем массив из трех обещаний, одно из которых отклонено. Затем мы используем Promise.any, чтобы дождаться выполнения первого обещания и записать его результат в консоль. Если все обещания отклонены, мы перехватываем ошибку и записываем сообщение в консоль.

Заключение

Промисы — это важная функция современного JavaScript, позволяющая обрабатывать асинхронные операции более эффективно и читабельно. Их можно использовать для цепочки асинхронных операций, параллельного выполнения нескольких промисов и более организованной обработки ошибок.

Поняв эти передовые методы работы с промисами, вы сможете вывести свой асинхронный код JavaScript на новый уровень и написать более эффективный, удобочитаемый и удобный для сопровождения код.

Купи мне кофе