> Как отменить или обработать промис в JavaScript (JavaScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: TYMY

Стек: JavaScript

> Пример ответа

Короткий ответ

Промис в JavaScript нельзя отменить нативно - у него нет метода .cancel(). Для обработки используют try/catch с async/await или .catch(). Для имитации отмены применяют AbortController (в fetch) или оборачивают промис в reject при флаге отмены. В продакшене часто используют сторонние библиотеки (например, Bluebird с .cancel()) или паттерн с токеном отмены.

Подробное объяснение

Промис по спецификации - это объект с тремя состояниями: pending, fulfilled, rejected. Переход из pending в любое другое состояние необратим. Отмена как четвёртое состояние отсутствует. Это сделано для простоты и предсказуемости цепочек промисов.

Для обработки ошибок и отказов используется .catch() или try/catch в async/await. Если нужно прервать выполнение асинхронной операции, используют AbortController - он передаёт сигнал в fetch или другие API, поддерживающие отмену. Для собственных промисов применяют обёртку с проверкой флага отмены: при установке флага промис реджектится с кастомной ошибкой.

На практике отмена часто реализуется через паттерн "token cancellation": создаётся объект с флагом isCancelled, который проверяется внутри асинхронной функции. Если флаг установлен, функция не выполняет коллбэк resolve, а реджектит промис или просто завершается.

На практике

В современных приложениях (React, Node.js) отмена промисов критична для:

  • предотвращения утечек памяти при размонтировании компонента
  • отмены устаревших запросов при повторном вызове
  • тайм-аутов и прерывания долгих операций

В React для отмены запросов при unmount используют useEffect с cleanup-функцией, где вызывается abort(). В Node.js AbortController применяют для отмены HTTP-запросов, чтения потоков и таймеров.

Для собственных асинхронных функций (не fetch) удобно создать утилиту makeCancelable, которая оборачивает промис и добавляет метод cancel(), реджектящий промис с кастомной ошибкой.

Пример кода

JAVASCRIPT
// Отмена fetch через AbortController
function fetchWithCancel(url) {
const controller = new AbortController();
const promise = fetch(url, { signal: controller.signal });
return { promise, cancel: () => controller.abort() };
}
// Использование
const { promise, cancel } = fetchWithCancel('/api/data');
promise.then(data => console.log(data)).catch(err => {
if (err.name === 'AbortError') console.log('Запрос отменён');
});
cancel(); // отменяем запрос
// Обёртка для отмены любого промиса
function makeCancelable(promise) {
let rejectFn;
const wrapped = new Promise((resolve, reject) => {
rejectFn = reject;
promise.then(resolve).catch(reject);
});
return {
promise: wrapped,
cancel: () => rejectFn(new Error('Promise cancelled'))
};
}

Как отвечать на собеседовании

Начни с чёткого утверждения: промисы нельзя отменить нативно, но есть обходные пути. Упомяни AbortController как стандартный механизм для fetch и других Web API. Покажи понимание разницы между отменой (прерывание выполнения) и обработкой ошибок (catch). Приведи пример из практики - отмена запроса при размонтировании React-компонента. Упомяни, что в Node.js есть AbortSignal.timeout() для тайм-аутов. Если спросят про Bluebird - скажи, что это легаси-подход, в современном коде предпочтительнее нативные решения.

Что проверяет интервьюер

  • Понимание асинхронной модели JavaScript и состояний промиса
  • Знание современных Web API (AbortController, AbortSignal)
  • Умение проектировать отменяемые асинхронные операции
  • Понимание trade-off между отменой и обработкой ошибок
  • Опыт работы с реальными кейсами (React, Node.js)

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

  • Утверждение, что .cancel() существует у промиса - это неверно
  • Путаница между отменой промиса и остановкой выполнения кода (промис не останавливает выполнение функции)
  • Игнорирование обработки ошибки отмены (AbortError) - её нужно ловить отдельно
  • Создание утечек памяти: невызванный reject при отмене оставляет промис в pending навсегда
  • Использование глобальных флагов отмены вместо изолированных токенов - это приводит к багам при параллельных вызовах

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью