Перевод статьи Ganapati V S «Aborting a fetch request»
Используйте AbortController для отмены запроса.
В настоящее время существует два основных способа совершения запросов: XMLHttpRequest и fetch. XMLHttpRequest существует уже долгое время, а fetch был добавлен в ES6.
У XMLHttpRequest всегда была возможность отмены запроса. И отмена этого запроса выглядит так:
let xhr = new XMLHttpRequest();
xhr.method = 'GET';
xhr.url = 'https://slowmo.glitch.me/5000';
xhr.open(method, url, true);
xhr.send();
// Отменяем запрос по клику.
abortButton.addEventListener('click', function() {
xhr.abort();
});
У fetch-запроса изначально не было способа отмены. Соответствующее ишью было открыто на гитхабе в 2015 году. Кроме того, было много попыток решить проблему без изменения спецификации. Например, отменяемые промисы и другие хаки.
Но теперь мы, наконец-то, имеет AbortController и AbortSignal API. Этот API предоставляется через DOM-стандарт, а не является частью языка.
Что такое AbortController?
Вот описание спецификации:
Хотя промисы и не имеют встроенную функцию отмены, многие API используют их. AbortController предоставляет метод abort(), который переключает состояние соответствующего объекта AbortSignal. API, которые хотят использовать прерывание, может принять объект AbortSignal и использовать его состояние, чтобы решить что делать.
// Создаём AbortController
const controller = new AbortController();
const signal = controller.signal;
// Слушает signal, коллбэк выполняет controller.abort()
signal.addEventListener('abort', () => {
console.log(signal.aborted); // true
});
// Отменяет позднее, уведомляя signal
controller.abort();
Как отменить fetch-запрос, используя AbortController?
Fetch принимает AbortSignal как часть второго аргумента.
const controller = new AbortController();
const signal = controller.signal;
// API отвечает через 5 секунд.
// Обратите внимание: 'signal' — второй аргумент.
fetch('https://slowmo.glitch.me/5000', { signal })
.then(r => r.json())
.then(response => console.log(response))
.catch(err => {
if (err.name === 'AbortError') {
console.log('Fetch was aborted');
} else {
console.error('Oops!', err);
}
});
// Отменяет запрос через 2 секунды.
setTimeout(() => {
controller.abort();
}, 2000);
Отмена запроса отменяет и отправку, и получение. Запрос выдаёт ошибку new DOMException(‘Aborted’, ‘AbortError’).
Тот же AbortSignal (signal в коде выше) может использоваться для отмены нескольких fetch-запросов.
AbortController работает не только с fetch-запросами. Это часть общего API и он может использоваться для отмены асинхронных задач. Например, с помощью него можно создавать отменяемые промисы.
Кроме того, заметьте, что многие старые браузеры не поддерживают AbortController. Но вы можете использовать полифилы:
Поделиться