Gernar
JavaScript: асинхронность

Что такое Promise

Разбор вопроса «Что такое Promise» для Frontend Developer: что проверяет интервьюер, ключевые тезисы, практические примеры и частые ошибки.

Вопрос

Что такое Promise

Профессия

Frontend Developer

Что хочет услышать интервьюер

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

Ключевые тезисы

  • Promise — это объект, представляющий результат асинхронной операции, которая может завершиться успешно или с ошибкой.
  • Promise имеет три состояния: pending (ожидание), fulfilled (выполнено успешно) и rejected (выполнено с ошибкой).
  • Для обработки результата используются методы then() для успешного выполнения и catch() для ошибок.
  • Цепочки Promise позволяют упростить работу с последовательными асинхронными операциями.
  • Promise помогает избежать «callback hell» и делает код более читаемым и управляемым.

Подробный ответ

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

Три состояния Promise

  • Pending (ожидание) — начальное состояние, операция ещё не завершена
  • Fulfilled (выполнен) — операция завершена успешно, результат доступен
  • Rejected (отклонён) — операция завершена с ошибкой

> Важно: После перехода из состояния pending в fulfilled или rejected, промис становится неизменяемым — его состояние нельзя изменить повторно.

Основные методы

  • .then(onFulfilled, onRejected) — обработка успешного результата или ошибки
  • .catch(onRejected) — обработка ошибки (сахар для .then(null, onRejected))
  • .finally(callback) — выполняется независимо от результата

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

МетодОписание
Promise.all()Ждёт выполнения всех промисов, отклоняется при первой ошибке
Promise.allSettled()Ждёт завершения всех промисов (и успешных, и с ошибками)
Promise.race()Возвращает результат первого завершившегося промиса
Promise.any()Возвращает результат первого успешного промиса

Promise и async/await

async/await — это синтаксический сахар над промисами, делающий асинхронный код похожим на синхронный. Под капотом await работает с теми же промисами.

Практические примеры

Пример 1

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

const fetchUser = new Promise((resolve, reject) => {
  setTimeout(() => {
    const user = { id: 1, name: 'Alice' };
    resolve(user);
    // или reject(new Error('User not found'));
  }, 1000);
});

fetchUser
  .then(user => console.log(user.name))  // 'Alice'
  .catch(error => console.error(error))
  .finally(() => console.log('Done'));

resolve переводит промис в состояние fulfilled, reject — в rejected.

Пример 2

Promise.all vs Promise.allSettled

const p1 = Promise.resolve(1);
const p2 = Promise.reject(new Error('fail'));
const p3 = Promise.resolve(3);

// Promise.all — падает при первой ошибке
Promise.all([p1, p2, p3])
  .catch(err => console.log(err.message)); // 'fail'

// Promise.allSettled — ждёт все результаты
Promise.allSettled([p1, p2, p3])
  .then(results => console.log(results));
// [
//   { status: 'fulfilled', value: 1 },
//   { status: 'rejected', reason: Error('fail') },
//   { status: 'fulfilled', value: 3 }
// ]

Promise.allSettled полезен, когда нужно дождаться всех результатов, даже при ошибках.

Пример 3

Цепочка промисов

fetch('/api/user/1')
  .then(response => response.json())
  .then(user => fetch(`/api/posts?userId=${user.id}`))
  .then(response => response.json())
  .then(posts => console.log(posts))
  .catch(error => console.error('Ошибка:', error));

Каждый .then() возвращает новый промис, позволяя выстраивать последовательные операции.

Частые ошибки

  • Необработанные ошибки: кандидаты часто забывают добавлять метод catch() для обработки ошибок, что может привести к непредсказуемому поведению программы.
  • Смешивание синхронного и асинхронного кода: некоторые кандидаты пытаются использовать Promise для синхронных операций, что не только излишне, но и может усложнить код.

Связанные темы

  • Async/await: синтаксический сахар для работы с Promise, который делает код еще более читаемым.
  • Callback functions: традиционный способ работы с асинхронностью в JavaScript.
  • Event Loop: механизм, который управляет выполнением асинхронного кода в JavaScript.

Follow-up вопросы

Какие методы используются для работы с Promise?

Уровень: basic

Основные методы — then(), catch() и finally(). then() обрабатывает успешный результат, catch() — ошибки, а finally() выполняется в любом случае, независимо от результата.

Что такое цепочка Promise и как она работает?

Уровень: intermediate

Цепочка Promise — это последовательное выполнение асинхронных операций, где результат одного Promise передается в следующий через then(). Это позволяет избежать вложенных колбэков и упрощает код.

Как можно создать собственный Promise?

Уровень: intermediate

Promise создается с помощью конструктора new Promise(), который принимает функцию с двумя аргументами — resolve и reject. resolve вызывается при успешном выполнении, а reject — при ошибке.

Что такое Promise.all и для чего он используется?

Уровень: advanced

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

Как обработать ошибку в цепочке Promise?

Уровень: intermediate

Ошибка в цепочке Promise обрабатывается с помощью метода catch(), который можно добавить в конец цепочки. Он перехватывает любую ошибку, возникшую в предыдущих then().

Содержание