Skip to main content

Що роблять AbortController і AbortSignal?

Що таке AbortController

AbortController - це контролер, який створює сигнал (AbortSignal) і вміє його "смикати" (скасовувати).

Простіше кажучи: AbortController - це "пульт", AbortSignal - це "провід", який підключається до операції.


Приклад

javascript
const controller = new AbortController(); const { signal } = controller; fetch('https://example.com/data', { signal }) .then(res => res.json()) .then(data => console.log('Успіх:', data)) .catch(err => { if (err.name === 'AbortError') { console.log('Запит скасовано!'); } else { console.error('Помилка:', err); } }); // Скасовуємо запит через 2 секунди setTimeout(() => controller.abort(), 2000);

Що відбувається:

  1. Створюється контролер.
  2. З нього дістається signal.
  3. signal передається у fetch.
  4. Через 2 секунди викликається controller.abort().
  5. fetch переривається і повертає помилку AbortError.

Як це влаштовано всередині

AbortController

  • Має методи:

    javascript
    controller.abort(reason?) // скасувати операцію controller.signal // посилання на сигнал

AbortSignal

  • Містить стан:

    javascript
    signal.aborted // true, якщо вже скасовано
  • Може слухати подію:

    javascript
    signal.addEventListener('abort', () => console.log('Скасування!'));

Приклад роботи з кількома завданнями

Ти можеш використовувати один контролер для кількох операцій одразу:

javascript
const controller = new AbortController(); fetch('/users', { signal: controller.signal }); fetch('/posts', { signal: controller.signal }); // скасовуємо обидві операції одразу controller.abort();

Обидва запити будуть перервані.


Можна вказати причину скасування

javascript
controller.abort('Ручне скасування'); signal.addEventListener('abort', e => { console.log(e.target.reason); // "Ручне скасування" });

(Підтримується в сучасних браузерах і Node 18+)


Використання з Promise.race для таймауту

javascript
function fetchWithTimeout(url, ms) { const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), ms); return fetch(url, { signal: controller.signal }) .finally(() => clearTimeout(timeout)); } fetchWithTimeout('/api/data', 2000) .then(r => r.json()) .then(console.log) .catch(err => { if (err.name === 'AbortError') console.log('Таймаут!'); });

Зручний шаблон: скасування після завершення часу.


Можна слухати скасування вручну (не лише у fetch)

javascript
function wait(ms, signal) { return new Promise((resolve, reject) => { const timeout = setTimeout(resolve, ms); signal.addEventListener('abort', () => { clearTimeout(timeout); reject(new Error('Скасовано')); }); }); } const controller = new AbortController(); wait(5000, controller.signal).catch(console.error); setTimeout(() => controller.abort(), 2000);

Тут wait() - користувацька функція, але вона вміє реагувати на AbortSignal, як fetch.


Підтримка

Працює в:

  • усіх сучасних браузерах (Chrome, Firefox, Safari, Edge)
  • Node.js 16.5+ (у fetch, stream, setTimeout)

Проста аналогія

AbortController - це пульт керування.

AbortSignal - це провід, з'єднаний із завданням.

Коли натискаєш abort(), сигнал проходить по проводу і повідомляє завданню: "Зупинись!"


ПІДСУМОК

Об'єктЩо робитьОсновні властивості/методи
AbortControllerКерує скасуванням.abort(), .signal
AbortSignalПередається в операцію, щоб слухати скасування.aborted, .addEventListener('abort')
Типова помилкаAbortError - викидається при скасуванні
Типові сценаріїСкасування fetch, таймаути, переривання кількох завдань

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.