Node.js Promise

Promise — одна из ключевых концепций для обработки асинхронных операций в Node.js.

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

В этой статье подробно описаны концепция, использование и распространённые шаблоны Promise.


Что такое Promise?

Promise — это объект, представляющий конечное завершение или неудачу асинхронной операции. Он имеет три состояния:

  1. Pending (ожидание): начальное состояние, ни успешное, ни неуспешное
  2. Fulfilled (успешное): Операция успешно завершена
  3. Rejected (неудачное): Операция не удалась

Как только состояние Promise изменится (из pending в fulfilled или rejected), оно больше не изменится.


Создание Promise

В Node.js вы можете использоватьPromiseконструктор для создания нового объекта Promise:

Пример

const myPromise = new Promise((resolve, reject) => {
  // Асинхронная операция
  const success = true; // Предположим, это результат асинхронной операции
 
  if (success) {
    resolve('Операция выполнена!'); // Состояние становится fulfilled
  } else {
    reject('Операция не удалась!'); // Состояние становится rejected
  }
});

Использование Promise

Promise предоставляет.then()и.catch()метод для обработки случаев успеха и неудачи:

Пример

myPromise
  .then((result) => {
    console.log(result); // Вывод: "Операция выполнена!"
  })
  .catch((error) => {
    console.error(error); // Вывод: "Операция не удалась!"
  });

Цепочка Promise

Сила Promise заключается в его способности связывать несколько асинхронных операций в цепочку:

Пример

function asyncOperation1() {
  return new Promise((resolve) => {
    setTimeout(() => resolve('First step completed'), 1000);
  });
}

function asyncOperation2(data) {
  return new Promise((resolve) => {
    setTimeout(() => resolve(`${data},Second step completed`), 1000);
  });
}

asyncOperation1()
  .then((result) => asyncOperation2(result))
  .then((finalResult) => {
    console.log(finalResult); // Вывод: "First step completed, Second step completed"
  })
  .catch((error) => {
    console.error('Error in chain:', error);
  });

Статические методы Promise

Promise предоставляет несколько полезных статических методов:

Promise.all()

Ожидает завершения всех промисов или сбоя любого одного промиса:

Пример

const promise1 = Promise.resolve('first');
const promise2 = Promise.resolve('second');

Promise.all([promise1, promise2])
  .then((results) => {
    console.log(results); // Вывод: ['first', 'second']
  });

Promise.race()

Возвращает Promise, который завершается первым (выполняется или отклоняется):

Пример

const promise1 = new Promise((resolve) => setTimeout(resolve, 500, 'first'));
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, 'second'));

Promise.race([promise1, promise2])
  .then((result) => {
    console.log(result); // Вывод: "second"
  });

Обработка ошибок

Обработка ошибок Promise может выполняться через.catch()или.then()второй параметр .then:

Пример

someAsyncFunction()
  .затем(
    (result) => { /* Обработать успех */ },
    (error) => { /* Обработать сбой */ }
  );

// Или
someAsyncFunction()
  .then((result) => { /* Обработать успех */ })
  .catch((error) => { /* Обработать все ошибки */ });

Синтаксис async/await

В ES2017 был представлен синтаксис async/await, который делает использование Promise более интуитивным:

Пример

async function runOperations() {
  try {
    const result1 = await asyncOperation1();
    const result2 = await asyncOperation2(result1);
    console.log(result2);
  } catch (error) {
    console.error(error);
  }
}

runOperations();

Лучшие практики

  1. Всегда обрабатывайте ошибки: Не игнорируйте.catch()или try-catch
  2. Избегайте вложенности: используйте цепочки или async/await, чтобы код оставался плоским
  3. Именуйте промисы: давайте переменным Promise осмысленные имена
  4. Возвращайте промисы: возвращайте промисы из функций, чтобы можно было строить цепочки
Другие расширения