← Назад к вопросам

Что такое Promise?

1.0 Junior🔥 271 комментариев
#Node.js и JavaScript

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Promise в JavaScript/Node.js

Promise — это объект в JavaScript, который представляет результат асинхронной операции (может быть успешно выполнена или отклонена). Это фундамент асинхронного программирования в современном Node.js.

Определение

Promise — это объект, который содержит:

  • Состояние (state): pending, fulfilled (успех) или rejected (ошибка)
  • Значение (value): результат успешной операции или причина ошибки
  • Методы: then(), catch(), finally()

Жизненный цикл Promise

// Состояние: PENDING (ожидание)
const promise = new Promise((resolve, reject) => {
  // resolve() или reject() изменит состояние
});

// После вызова resolve() → FULFILLED (выполнено)
// После вызова reject() → REJECTED (отклонено)
// Состояние не может измениться обратно!

Базовый синтаксис

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    const success = true;
    if (success) {
      resolve('Operation successful!'); // FULFILLED
    } else {
      reject('Operation failed!');       // REJECTED
    }
  }, 1000);
});

// Обработка результата
myPromise
  .then((result) => {
    console.log('Success:', result);
  })
  .catch((error) => {
    console.error('Error:', error);
  })
  .finally(() => {
    console.log('Cleanup');
  });

then() — обработка успеха

const promise = Promise.resolve(5);

promise
  .then((value) => {
    console.log(value); // 5
    return value * 2;   // Возвращаем новое значение
  })
  .then((value) => {
    console.log(value); // 10
  });

// Цепочка then() создаёт новый Promise

catch() — обработка ошибок

const failedPromise = Promise.reject(new Error('Something went wrong'));

failedPromise
  .catch((error) => {
    console.error('Caught error:', error.message);
    // Если здесь return значение → следующий then получит его
    return 'recovered';
  })
  .then((value) => {
    console.log(value); // 'recovered'
  });

// catch() можно использовать вместо then(null, errorHandler)

finally() — очистка ресурсов

const promise = fetchData();

promise
  .then((data) => console.log('Data:', data))
  .catch((error) => console.error('Error:', error))
  .finally(() => {
    // Выполнится в ЛЮБОМ случае (успех или ошибка)
    console.log('Closing connection...');
  });

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

Promise.resolve() — создать успешный Promise

const promise = Promise.resolve('Hello');
// То же самое что:
// new Promise((resolve) => resolve('Hello'));

promise.then((value) => console.log(value)); // Hello

Promise.reject() — создать отклонённый Promise

const promise = Promise.reject(new Error('Failed'));
// То же самое что:
// new Promise((resolve, reject) => reject(new Error('Failed')));

promise.catch((error) => console.error(error)); // Error: Failed

Promise.all() — ждать все Promise

const promise1 = fetch('/api/users');
const promise2 = fetch('/api/posts');
const promise3 = fetch('/api/comments');

Promise.all([promise1, promise2, promise3])
  .then(([users, posts, comments]) => {
    console.log('All done:', { users, posts, comments });
  })
  .catch((error) => {
    // Если ЛЮБОЙ Promise rejected → сразу в catch
    console.error('One failed:', error);
  });

Promise.race() — первый результат

const timeout = new Promise((_, reject) => 
  setTimeout(() => reject('Timeout'), 5000)
);
const request = fetch('/api/slow-endpoint');

Promise.race([request, timeout])
  .then((data) => console.log('Success:', data))
  .catch((error) => console.error('Timeout or error:', error));

Promise.allSettled() — все результаты

const promises = [
  Promise.resolve(1),
  Promise.reject(new Error('Failed')),
  Promise.resolve(3),
];

Promise.allSettled(promises)
  .then((results) => {
    console.log(results);
    // [
    //   { status: 'fulfilled', value: 1 },
    //   { status: 'rejected', reason: Error },
    //   { status: 'fulfilled', value: 3 },
    // ]
  });

Async/Await — синтаксический сахар для Promise

Async/Await делает код с Promise более читаемым, как синхронный:

// Без async/await (с Promise)
function getUser(id) {
  return fetch(`/api/users/${id}`)
    .then((res) => res.json())
    .then((user) => {
      if (user.id === 1) {
        return fetch(`/api/users/${id}/profile`);
      }
      return user;
    })
    .then((data) => data.json())
    .catch((error) => console.error('Error:', error));
}

// С async/await (более читаемо!)
async function getUser(id) {
  try {
    const res = await fetch(`/api/users/${id}`);
    let user = await res.json();
    
    if (user.id === 1) {
      const profileRes = await fetch(`/api/users/${id}/profile`);
      user = await profileRes.json();
    }
    
    return user;
  } catch (error) {
    console.error('Error:', error);
    throw error;
  }
}

Реальный пример: Node.js API

// Без обработки Promise правильно
app.get('/users/:id', (req, res) => {
  const user = getUserFromDB(req.params.id); // Возвращает Promise!
  res.json(user); // Ошибка! user — это Promise, не объект
});

// Правильно с async/await
app.get('/users/:id', async (req, res) => {
  try {
    const user = await getUserFromDB(req.params.id);
    res.json(user);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Или с .then().catch()
app.get('/users/:id', (req, res) => {
  getUserFromDB(req.params.id)
    .then((user) => res.json(user))
    .catch((error) => res.status(500).json({ error: error.message }));
});

Типичные ошибки с Promise

Ошибка 1: Забыть return в цепочке then()

// Плохо
promise
  .then((value) => {
    const result = value * 2; // return забыли!
  })
  .then((result) => {
    console.log(result); // undefined!
  });

// Хорошо
promise
  .then((value) => {
    return value * 2; // или просто: const result = value * 2; return result;
  })
  .then((result) => {
    console.log(result); // Правильное значение
  });

Ошибка 2: Забыть catch() на конце цепочки

// Плохо — необработанное отклонение
promise
  .then((value) => {
    throw new Error('Oops');
  })
  .then((value) => {
    console.log(value);
  });
// Ошибка будет проигнорирована!

// Хорошо
promise
  .then((value) => {
    throw new Error('Oops');
  })
  .then((value) => {
    console.log(value);
  })
  .catch((error) => {
    console.error('Handled:', error);
  });

Ошибка 3: Создать Promise hell (Callback hell для Promise)

// Плохо — вложенные then
getUser(1)
  .then((user) => {
    getProfile(user.id).then((profile) => {
      getPosts(user.id).then((posts) => {
        console.log(user, profile, posts);
      });
    });
  });

// Хорошо — цепочка then
getUser(1)
  .then((user) => getProfile(user.id).then((profile) => ({ user, profile })))
  .then(({ user, profile }) => getPosts(user.id).then((posts) => ({ user, profile, posts })))
  .then(({ user, profile, posts }) => console.log(user, profile, posts));

// Или ещё лучше — async/await
async function getFullUserData(id) {
  const user = await getUser(id);
  const profile = await getProfile(user.id);
  const posts = await getPosts(user.id);
  return { user, profile, posts };
}

Promise vs Callback vs Async/Await

Callback (старый подход, избегать):

function getUser(id, callback) {
  setTimeout(() => {
    callback(null, { id, name: 'John' });
  }, 1000);
}

getUser(1, (error, user) => {
  if (error) console.error(error);
  else console.log(user);
});

Promise (современный подход):

function getUser(id) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({ id, name: 'John' });
    }, 1000);
  });
}

getUser(1).then((user) => console.log(user));

Async/Await (лучший подход):

async function getUser(id) {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve({ id, name: 'John' });
    }, 1000);
  });
}

const user = await getUser(1);
console.log(user);

Почему Promise важен

  1. Асинхронность — операции не блокируют основной поток
  2. Обработка ошибок — через catch() вместо try/catch
  3. Цепочки операций — связывать асинхронные операции
  4. Composability — Promise.all(), Promise.race() и т.д.
  5. Основа для async/await — современный способ писать асинхронный код