Що роблять AbortController і AbortSignal?
Що таке AbortController
AbortController - це контролер, який створює сигнал (AbortSignal) і вміє його "смикати" (скасовувати).
Простіше кажучи:
AbortController- це "пульт",AbortSignal- це "провід", який підключається до операції.
Приклад
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);Що відбувається:
- Створюється контролер.
- З нього дістається
signal. signalпередається уfetch.- Через 2 секунди викликається
controller.abort(). fetchпереривається і повертає помилкуAbortError.
Як це влаштовано всередині
AbortController
-
Має методи:
javascriptcontroller.abort(reason?) // скасувати операцію controller.signal // посилання на сигнал
AbortSignal
-
Містить стан:
javascriptsignal.aborted // true, якщо вже скасовано -
Може слухати подію:
javascriptsignal.addEventListener('abort', () => console.log('Скасування!'));
Приклад роботи з кількома завданнями
Ти можеш використовувати один контролер для кількох операцій одразу:
const controller = new AbortController();
fetch('/users', { signal: controller.signal });
fetch('/posts', { signal: controller.signal });
// скасовуємо обидві операції одразу
controller.abort();Обидва запити будуть перервані.
Можна вказати причину скасування
controller.abort('Ручне скасування');
signal.addEventListener('abort', e => {
console.log(e.target.reason); // "Ручне скасування"
});(Підтримується в сучасних браузерах і Node 18+)
Використання з Promise.race для таймауту
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)
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, таймаути, переривання кількох завдань |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.