Как отменить или обработать промис в JavaScript
Что проверяют
Понимаете ли вы, что у промиса нет отмены: он лишь представляет результат, а остановить можно только операцию, которая его породила. Следом обычно просят показать, как отменить запрос при уходе со страницы или при новом вводе в поиске.
Как отвечать
Сначала обработка. Промис бывает в состояниях pending, fulfilled и rejected и меняет состояние один раз. Ошибку ловят .catch() или try/catch вокруг await, очистку ставят в .finally(). Для группы: Promise.all падает на первой ошибке, Promise.allSettled ждёт всех и отдаёт статус каждого, Promise.any берёт первый успешный, а при общей неудаче бросает AggregateError. Непойманные отказы видны через событие unhandledrejection.
Для отмены стандартный инструмент это AbortController:
fetch(url, { signal }): послеcontroller.abort()промис отклоняется сDOMExceptionпо имениAbortError;- таймаут:
AbortSignal.timeout(5000)без ручногоsetTimeout, ошибка при срабатывании называетсяTimeoutError; - несколько причин:
AbortSignal.any([userSignal, AbortSignal.timeout(5000)]); - своя функция: принимает
signal, в начале вызываетsignal.throwIfAborted(), а долгие шаги подписываются на событиеabortс опцией{ once: true }; - библиотеки: axios принимает тот же
signal, старыйCancelTokenустарел.
Типичный сценарий во фронтенде: в useEffect создаёте контроллер, передаёте signal в запрос, а в функции очистки вызываете abort(). Тогда ответ старого запроса не перезапишет данные нового, а ошибку AbortError вы не показываете пользователю как сбой.
Где спотыкаются
Думают, что Promise.race с таймером отменяет запрос. Он лишь перестаёт ждать, а запрос продолжается и тратит трафик.
Ловят отмену общим обработчиком и показывают «Ошибка сети», хотя пользователь просто ушёл со страницы. Нужно проверять error.name.
Забывают, что fetch отклоняет промис только при сетевой ошибке. Ответы 404 и 500 приходят как успешные, и response.ok приходится проверять самим.