В веб-разработке при управлении асинхронными задачами, такими как извлечение данных и загрузка файлов, часто возникают ситуации, когда необходимо прервать операции. Интерфейс AbortSignal
, появившийся в DOM в современных веб-браузерах, предоставляет возможность корректно прервать асинхронные операции.
Рассмотрим два малоизвестных статических метода AbortSignal
: AbortSignal.timeout()
и AbortSignal.any()
. Эти методы предоставляют мощные возможности для эффективного управления асинхронными задачами и реагирования на них. Они полностью поддерживаются всеми основными веб-браузерами.
AbortSignal.timeout()
Статический метод AbortSignal.timeout()
предлагает удобный способ создания AbortSignal
, который автоматически выполняет прерывание по истечении заданного времени. Этот метод возвращает экземпляр AbortSignal
, который прерывается с исключением TimeoutError
DOMException, если указанное время истекает до завершения операции.
Он также прерывается с AbortError
DOMException, если пользователь инициирует действие остановки, например нажатие кнопки остановки браузера.
const fetchFile = async (url, timeout) => {
try {
const response = await fetch(url, {
signal: AbortSignal.timeout(timeout) 👈👈👈
});
const file = await response.blob();
// Обработка файла
console.log("File fetched successfully:", file);
} catch (error) {
handleFetchError(error);
}
};
const handleFetchError = (error) => {
switch (error.name) {
case "TimeoutError":
console.error("The operation timed out.");
break;
case "AbortError":
console.error("The fetch operation was aborted.");
break;
default:
console.error(`An error occurred: ${error.message}`);
}
};
// Пример использования
const fileUrl = "https://path_to_large_file.mp4";
const fetchTimeout = 5_000; // 5 секунд
fetchFile(fileUrl, fetchTimeout);
Этот пример демонстрирует использование AbortSignal.timeout()
для получения файла в пределах таймаута в 5 секунд. В зависимости от результата различают ошибки таймаута, прерывания, инициированные пользователем, и другие потенциальные ошибки.
AbortSignal.any()
Статический метод AbortSignal.any()
позволяет объединить несколько экземпляров AbortSignal
в один, что облегчает координацию действий по прерыванию. Он принимает iterable (итерируемый объект) сигналов прерывания и возвращает AbortSignal
, который прерывает работу всякий раз, когда любой из входных сигналов прерывается. Причину прерывания следует искать в первом сигнале, вызвавшем прерывание.
const cancelDownloadBtn = document.querySelector('button');
const userCancelController = new AbortController();
cancelDownloadBtn.addEventListener("click", () => {
userCancelController.abort();
});
const timeoutDuration = 1_000 * 60 * 5; // 5 минут
// Создание комбинированного сигнала для обработки отмены и таймаута
const timeoutSignal = AbortSignal.timeout(timeoutDuration);
const combinedSignal = AbortSignal.any([
userCancelController.signal,
timeoutSignal,
]);
try {
const response = await fetch(someUrlToDownload, {
signal: combinedSignal 👈👈👈
});
const downloadedContent = await response.blob();
// Обработка загруженного содержимого
} catch (error) {
if (error.name === "AbortError") {
// Обработка отмены
} else if (error.name === "TimeoutError") {
// Обработка таймаута
} else {
// Обработка других ошибок (например, ошибок с сетью)
}
}
В этом примере AbortSignal.any()
используется для создания комбинированного сигнала, который выполняет прерывание либо когда пользователь отменяет загрузку, либо по истечении таймаута в 5 минут, в зависимости от того, что произойдет раньше.
Его можно использовать с любым API, принимающим AbortSignal
, например:
document.querySelector('button').addEventListener(
'click',
() => { },
{
// Отмена события после 4 секунд
signal: AbortSignal.timeout(4_000),
}
);
Читайте также:
- Когда не стоит использовать метод find() в JavaScript
- Топ-5 новых функций JavaScript ES12, которые облегчат вам жизнь
- 8 неэффективных практик JavaScript, которых лучше избегать
Читайте нас в Telegram, VK и Дзен
Перевод статьи Netanel Basal: Harnessing Control: Exploring JavaScript’s AbortSignal Timeout and Any Methods