← Назад к вопросам

С помощью чего отменяется fetch запрос в JavaScript?

2.0 Middle🔥 221 комментариев
#JavaScript Core#Браузер и сетевые технологии

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Отмена fetch-запросов в JavaScript

В JavaScript для отмены fetch-запросов используется стандартный API AbortController, который был введен в спецификации DOM Living Standard. Этот механизм предоставляет возможность прерывать асинхронные операции, включая сетевые запросы.

Основной механизм: AbortController и AbortSignal

AbortController — это объект, который позволяет создавать сигналы для прерывания операций. Основной сценарий использования:

// Создаем контроллер
const controller = new AbortController();
const signal = controller.signal;

// Используем сигнал в fetch-запросе
fetch('https://api.example.com/data', {
  signal: signal,
  method: 'GET'
})
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => {
    if (error.name === 'AbortError') {
      console.log('Запрос был отменен');
    } else {
      console.error('Произошла ошибка:', error);
    }
  });

// Для отмены запроса
controller.abort();

Ключевые особенности реализации

  • AbortSignal — объект, который передается в параметры fetch и служит "мостом" между контроллером и запросом
  • Метод abort() — инициирует прерывание операции
  • Событие abort — сигнал генерирует событие, на которое можно подписаться
  • AbortError — специальный тип ошибки, который возникает при отмене запроса

Расширенный пример с таймаутом

// Автоматическая отмена через 5 секунд
const abortFetchAfterTimeout = (url, timeout = 5000) => {
  const controller = new AbortController();
  const signal = controller.signal;
  
  // Устанавливаем таймаут для автоматической отмены
  const timeoutId = setTimeout(() => {
    controller.abort();
    console.log(`Запрос к ${url} отменен по таймауту`);
  }, timeout);
  
  return fetch(url, { signal })
    .then(response => {
      clearTimeout(timeoutId);
      return response.json();
    })
    .catch(error => {
      clearTimeout(timeoutId);
      if (error.name === 'AbortError') {
        throw new Error('Запрос отменен по таймауту');
      }
      throw error;
    });
};

// Использование
abortFetchAfterTimeout('https://api.example.com/slow-endpoint', 3000)
  .then(data => console.log('Данные:', data))
  .catch(error => console.error('Ошибка:', error.message));

Совместное использование нескольких запросов

Один AbortController может использоваться для отмены нескольких запросов одновременно:

const controller = new AbortController();
const { signal } = controller;

// Несколько запросов с одним сигналом
const requests = [
  fetch('/api/users', { signal }),
  fetch('/api/posts', { signal }),
  fetch('/api/comments', { signal })
];

// Отмена всех запросов
document.getElementById('cancel-button').addEventListener('click', () => {
  controller.abort();
});

// Обработка всех промисов
Promise.all(requests)
  .then(responses => Promise.all(responses.map(r => r.json())))
  .catch(error => {
    if (error.name === 'AbortError') {
      console.log('Все запросы отменены');
    }
  });

Особенности и лучшие практики

  1. Проверка поддержки браузером: Хотя современные браузеры поддерживают AbortController, стоит проверять его наличие:

    if ('AbortController' in window) {
      // Используем AbortController
    } else {
      // Альтернативная реализация или сообщение об ошибке
    }
    
  2. Очистка ресурсов: После отмены запроса или его завершения, рекомендуется очищать связанные ресурсы (таймеры, обработчики событий).

  3. Состояние сигнала: Можно проверять, был ли уже отменен сигнал:

    if (signal.aborted) {
      console.log('Сигнал уже был отменен');
      return;
    }
    
  4. Слушатели событий: На сигнал можно подписаться для реакции на отмену:

    signal.addEventListener('abort', () => {
      console.log('Сигнал отменен, выполняем очистку');
      // Дополнительная логика очистки
    });
    

Историческая альтернатива и полифиллы

До появления AbortController разработчики использовали различные хаки, например, обертку над XMLHttpRequest или прерывание Promise.race с таймаутом. Для поддержки старых браузеров существуют полифиллы:

// Пример простого полифилла для старых браузеров
if (!window.AbortController) {
  window.AbortController = class {
    constructor() {
      this.signal = {
        aborted: false,
        onabort: null
      };
    }
    abort() {
      this.signal.aborted = true;
      if (this.signal.onabort) {
        this.signal.onabort();
      }
    }
  };
}

Заключение

AbortController — это стандартизированный, эффективный и надежный способ управления отменой fetch-запросов в JavaScript. Он обеспечивает:

  • Консистентный API для всех асинхронных операций
  • Возможность групповой отмены нескольких запросов
  • Интеграцию с другими Web API (например, с addEventListener)
  • Улучшенный контроль над сетевыми операциями

Использование этого механизма значительно улучшает пользовательский опыт, позволяя избежать нежелательных сетевых запросов при навигации, закрытии компонентов или выполнении условий таймаута.