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

Как обрабатывать Promise

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

Вопрос

Как обрабатывать Promise

Профессия

Frontend Developer

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

Интервьюер хочет убедиться, что кандидат понимает, как работать с асинхронными операциями в JavaScript, знает основные методы обработки Promise и умеет применять их на практике. Также важно показать знакомство с современными подходами, такими как async/await.

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

  • Promise — это объект, представляющий результат успешного или неудачного завершения асинхронной операции. Он имеет три состояния: pending, fulfilled и rejected.
  • Для обработки Promise используются методы .then() (для успешного выполнения), .catch() (для обработки ошибок) и .finally() (для выполнения кода независимо от результата).
  • Метод .then() принимает два аргумента: колбэк для успешного выполнения и колбэк для ошибки (опционально).
  • Для работы с несколькими Promise можно использовать Promise.all(), Promise.race(), Promise.allSettled() и Promise.any().
  • Async/await — это синтаксический сахар над Promise, который позволяет писать асинхронный код в более читаемом синхронном стиле.

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

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

Для работы с несколькими Promise существуют специальные методы: Promise.all() ожидает выполнения всех Promise, Promise.race() возвращает результат первого выполнившегося Promise, Promise.allSettled() ждет завершения всех Promise и возвращает их результаты, а Promise.any() возвращает первый успешно выполнившийся Promise.

Async/await — это синтаксический сахар над Promise, который позволяет писать асинхронный код в более привычном синхронном стиле. Ключевое слово async перед функцией указывает, что она возвращает Promise, а await используется для ожидания выполнения Promise внутри такой функции.

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

Пример 1

Пример обработки Promise с .then() и .catch():

fetch('https://api.example.com/data')

.then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Ошибка:', error));

Пример 2

Пример использования Promise.all():

const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
Promise.all([promise1, promise2])
  .then(values => console.log(values)); // [1, 2]

Пример 3

Пример использования async/await:

async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Ошибка:', error);
  }
}

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

  • Необработанные ошибки: забывают добавлять .catch() для обработки ошибок в цепочке Promise.
  • Путаница между Promise.all() и Promise.race(): не понимают разницы в их поведении.
  • Использование await вне async функции: это приводит к синтаксической ошибке.

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

  • Event Loop и механизм работы асинхронного кода в JavaScript.
  • Работа с Fetch API и XMLHttpRequest.
  • Генераторы и итераторы в JavaScript.

Follow-up вопросы

В чем разница между Promise.all() и Promise.race()?

Уровень: intermediate

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

Как обработать ошибку в цепочке .then() без использования .catch()?

Уровень: basic

Можно передать второй аргумент в .then(), который будет вызван в случае ошибки. Например: .then(successCallback, errorCallback). Однако такой подход менее удобен для централизованной обработки ошибок.

Как работает async/await под капотом?

Уровень: advanced

Async/await преобразуется в цепочку Promise компилятором. Ключевое слово async делает функцию асинхронной, а await приостанавливает выполнение функции до разрешения Promise. Ошибки обрабатываются через try/catch.

Что вернет Promise.allSettled() и чем он отличается от Promise.all()?

Уровень: intermediate

Promise.allSettled() всегда дожидается завершения всех Promise и возвращает массив объектов с результатами (со статусом 'fulfilled' или 'rejected'). В отличие от Promise.all(), он не отклоняется при ошибке в одном из Promise.

Как отменить выполнение Promise?

Уровень: advanced

Нативно Promise нельзя отменить, но можно использовать обходные пути: AbortController (для fetch), флаги или сторонние библиотеки (например, Bluebird). В современных браузерах AbortController — предпочтительный способ.

Содержание