abort() - это метод объекта AbortController, который отправляет сигнал отмены.
Чаще всего его используют, чтобы отменить fetch():
const controller = new AbortController();
fetch("https://learn-javascript.ru/api/users", {
signal: controller.signal,
});
controller.abort();
Сам abort() не принимает участие в запросе напрямую. Он меняет состояние controller.signal, а операции, которые получили этот signal, реагируют на отмену.
Синтаксис
controller.abort()
Также можно передать причину отмены:
controller.abort(reason)
Где reason - любое значение, которое объясняет, почему операция была отменена.
Самый частый вариант - вызов без аргументов.
const controller = new AbortController();
controller.abort();
Метод возвращает undefined.
const result = controller.abort();
console.log(result); // undefined
Что происходит после abort()
У AbortController есть свойство signal.
До отмены signal.aborted равен false.
const controller = new AbortController();
console.log(controller.signal.aborted); // false
После вызова abort() значение меняется на true.
controller.abort();
console.log(controller.signal.aborted); // true
Это состояние уже не откатывается обратно. Если controller отменён, он остаётся отменённым.
abort() вместе с fetch()
Чтобы abort() мог отменить fetch(), нужно передать signal в настройки запроса.
const controller = new AbortController();
const promise = fetch("https://learn-javascript.ru/api/lessons", {
signal: controller.signal,
});
controller.abort();
Когда fetch() получает сигнал отмены, его промис отклоняется.
Обычно отмену обрабатывают через try...catch.
const controller = new AbortController();
try {
const response = await fetch("https://learn-javascript.ru/api/lessons", {
signal: controller.signal,
});
const lessons = await response.json();
console.log(lessons);
} catch (error) {
if (error.name === "AbortError") {
console.log("Запрос отменён");
} else {
console.log("Не удалось загрузить данные");
}
}
Если abort() вызван без своей причины, fetch() обычно попадает в catch с ошибкой AbortError.
Отмена по кнопке
Практический пример - кнопка отмены загрузки.
const controller = new AbortController();
const cancelButton = document.querySelector(".cancel-button");
cancelButton.addEventListener("click", () => {
controller.abort();
});
try {
const response = await fetch("https://learn-javascript.ru/api/articles", {
signal: controller.signal,
});
const articles = await response.json();
console.log(articles);
} catch (error) {
if (error.name === "AbortError") {
console.log("Пользователь отменил загрузку");
}
}
Здесь abort() вызывается только в момент клика.
Причина отмены
В abort() можно передать причину отмены.
const controller = new AbortController();
controller.abort("Пользователь закрыл окно");
console.log(controller.signal.aborted); // true
console.log(controller.signal.reason); // "Пользователь закрыл окно"
Это полезно, если нужно различать разные причины отмены внутри своего кода.
const controller = new AbortController();
controller.abort({
type: "timeout",
message: "Запрос выполнялся слишком долго",
});
console.log(controller.signal.reason.type); // "timeout"
Для обычной отмены fetch() чаще достаточно abort() без аргументов и проверки AbortError.
abort() для таймаута
fetch() не имеет настройки timeout, поэтому таймаут часто делают через setTimeout() и abort().
async function loadWithTimeout() {
const controller = new AbortController();
const timeoutId = setTimeout(() => {
controller.abort();
}, 3000);
try {
const response = await fetch("https://learn-javascript.ru/api/search", {
signal: controller.signal,
});
return await response.json();
} finally {
clearTimeout(timeoutId);
}
}
Если запрос завершится раньше, таймер будет очищен в finally.
Если запрос не успеет завершиться за 3 секунды, сработает abort().
Повторный вызов abort()
abort() можно вызвать несколько раз, но состояние уже не изменится повторно.
const controller = new AbortController();
controller.abort();
controller.abort();
console.log(controller.signal.aborted); // true
Первый вызов переводит signal в состояние отмены. Последующие вызовы не делают controller “более отменённым”.
Отменённый controller нельзя использовать заново
После abort() тот же signal уже отменён навсегда.
const controller = new AbortController();
controller.abort();
fetch("https://learn-javascript.ru/api/users", {
signal: controller.signal,
}); // запрос сразу будет отменён
Для нового запроса нужно создать новый AbortController.
const controller = new AbortController();
fetch("https://learn-javascript.ru/api/users", {
signal: controller.signal,
});
Это особенно важно в поиске, автодополнении и интерфейсах, где запросы запускаются много раз.
abort() не заменяет обработку ошибок
Отмена запроса - это не единственная возможная проблема.
try {
const response = await fetch("https://learn-javascript.ru/api/users", {
signal: controller.signal,
});
if (!response.ok) {
throw new Error(`Ошибка HTTP: ${response.status}`);
}
} catch (error) {
if (error.name === "AbortError") {
console.log("Запрос отменён");
} else {
console.log("Другая ошибка");
}
}
abort() отвечает только за отмену. HTTP-статусы, сетевые ошибки и ошибки чтения данных всё равно нужно обрабатывать отдельно.
Частые ошибки
Вызвать abort(), но не передать signal
const controller = new AbortController();
fetch("https://learn-javascript.ru/api/users");
controller.abort();
Такой вызов не отменит запрос, потому что fetch() не связан с controller.signal.
Правильно:
fetch("https://learn-javascript.ru/api/users", {
signal: controller.signal,
});
Использовать controller после отмены
const controller = new AbortController();
controller.abort();
console.log(controller.signal.aborted); // true
После этого для новой операции нужен новый AbortController.
Показывать ошибку пользователю при обычной отмене
Если пользователь сам нажал “Отмена”, это не всегда ошибка интерфейса.
catch (error) {
if (error.name === "AbortError") {
return;
}
console.log("Не удалось загрузить данные");
}
Так можно тихо обработать ожидаемую отмену и не показывать лишнее сообщение.
Быстрая памятка
abort()вызывают у объектаAbortController- метод отправляет сигнал отмены через
controller.signal - после вызова
signal.abortedстановитсяtrue abort()возвращаетundefined- чтобы отменить
fetch(), нужно передатьsignalв настройки запроса - отменённый
fetch()обычно попадает вcatchсAbortError - в
abort(reason)можно передать причину отмены - после
abort()controller нельзя использовать для нового запроса - для нового запроса создавайте новый
AbortController abort()не заменяет проверку HTTP-ошибок и обработку других ошибок
Коротко
abort() - это метод AbortController, который переводит signal в состояние отмены. Если этот signal был передан в fetch(), запрос будет отменён, а промис попадёт в catch. После вызова abort() controller нельзя использовать повторно: для новой операции создавайте новый AbortController.