Комментарий пользователя
Здравствуйте! Использую AbortController для отмены fetch, но при вызове controller.abort() промис fetch все равно завершается успешно или возвращает обычную ошибку. Как правильно делать отмену, чтобы отличать «отмена» от других ошибок?
Ответ специалиста
Добрый день, Владислав! Частая ошибка — не прокидывать signal в сам fetch или перехватывать ошибку и терять ее тип. Делайте так:
Передавайте signal в fetch напрямую.
const controller = new AbortController()
fetch('/api/long', { signal: controller.signal })
Различайте AbortError при catch.
try {
const resp = await fetch('/api/long', { signal:
controller.signal });
if (!resp.ok) throw new Error('HTTP ' + resp.status);
const data = await resp.json();
// обработка data
} catch (err) {
if (err.name === 'AbortError') {
// это явная отмена
console.log('Fetch aborted by user');
} else {
// другие ошибки сети/парсинга
console.error('Fetch error', err);
}
}
// отмена
controller.abort();
Если используете обертки/библиотеки — проверьте, что они поддерживают signal. Полифиллы или axios старых версий могут не передавать signal и вместо AbortError возвращать собственные ошибки.
Не «глушите» ошибку раньше времени. Если у вас общий catch, логируйте err.name — часто разработчики делают catch(() => {}) и теряют информацию.
А если нужен таймаут — реализуйте через отдельный AbortController и объединяйте события: при таймаут и при пользовательской отмене вызывайте controller.abort(). После этого вы будете получать DOMException с name ‘AbortError’ при отмене, а другие ошибки отличатся по name/message.
Разберем прикладные задачи по JS вместе, подпишитесь на рассылку Академии Selectel.