Spec-Zone.ru › Web APIs

AbortSignal

Базовая реализация Широко доступна *

Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна в браузерах с марта 2019 года.

* Некоторые части этой функции могут иметь различный уровень поддержки.

  • Подробнее
  • Полная совместимость
  • Отправить отзыв

Примечание: Эта функция доступна в Web Workers.

Интерфейс AbortSignal представляет собой объект сигнала, который позволяет взаимодействовать с асинхронной операцией (такой как запрос fetch) и прервать ее при необходимости через объект AbortController.

EventTarget AbortSignal

Свойства экземпляра

Также наследует свойства от своего родительского интерфейса, EventTarget.

AbortSignal.aborted Только для чтения

Логическое значение, указывающее, прервана ли операция (true) или нет (false).

AbortSignal.reason Только для чтения

Значение JavaScript, содержащее причину прерывания, после того как сигнал был прерван.

Статические методы

Также наследует методы от своего родительского интерфейса, EventTarget.

AbortSignal.abort()

Возвращает экземпляр AbortSignal, который уже установлен как прерванный.

AbortSignal.any()

Возвращает AbortSignal, который прерывает работу, когда любой из заданных сигналов прерывания прерывается.

AbortSignal.timeout()

Возвращает экземпляр AbortSignal, который автоматически прерывает работу после указанного времени.

Методы экземпляра

Также наследует методы от своего родительского интерфейса, EventTarget.

AbortSignal.throwIfAborted()

Выбрасывает причину прерывания сигнала (reason ), если сигнал прерван; в противном случае ничего не делает.

События

Также наследует события от своего родительского интерфейса, EventTarget.

Подпишитесь на это событие, используя addEventListener() или назначив обработчик событий свойству oneventname этого интерфейса.

abort

Вызывается, когда асинхронные операции, с которыми взаимодействует сигнал, прерываются. Также доступно через свойство onabort.

Примеры

Прерывание операции fetch с использованием явного сигнала

Следующий фрагмент кода демонстрирует, как можно использовать сигнал для прерывания загрузки видео с помощью API Fetch.

Сначала создается контроллер прерывания с использованием конструктора AbortController(), затем берется ссылка на связанный объект AbortSignal с помощью свойства AbortController.signal.

При инициализации запроса fetch мы передаем AbortSignal в качестве параметра в объекте опций запроса ({signal} ниже). Это связывает сигнал и контроллер с запросом fetch и позволяет прервать его, вызвав AbortController.abort(). Ниже показано, что операция fetch прерывается во втором обработчике событий, который был вызван при нажатии кнопки "Прервать" (abortBtn).

Когда вызывается abort(), обещание fetch() отклоняется с исключением типа DOMException с именем AbortError.

let controller;
const url = "video.mp4";

const downloadBtn = document.querySelector(".download");
const abortBtn = document.querySelector(".abort");

downloadBtn.addEventListener("click", fetchVideo);

abortBtn.addEventListener("click", () => {
  if (controller) {
    controller.abort();
    console.log("Download aborted");
  }
});

async function fetchVideo() {
  controller = new AbortController();
  const signal = controller.signal;

  try {
    const response = await fetch(url, { signal });
    console.log("Download complete", response);
    // process response further
  } catch (err) {
    console.error(`Download error: ${err.message}`);
  }
}

Если запрос прерывается после выполнения вызова fetch() но до чтения тела ответа, то попытка чтения тела ответа приведет к отклонению с исключением типа AbortError.

async function get() {
  const controller = new AbortController();
  const request = new Request("https://example.org/get", {
    signal: controller.signal,
  });

  const response = await fetch(request);
  controller.abort();
  // The next line will throw `AbortError`
  const text = await response.text();
  console.log(text);
}

Полный рабочий пример можно найти на GitHub; также его можно посмотреть в живом режиме.

Прерывание операции fetch по таймауту

Если вам нужно прервать операцию по таймауту, можно использовать статический метод AbortSignal.timeout(). Он возвращает AbortSignal объект, который автоматически прерывается по истечении определенного количества миллисекунд.

Фрагмент кода ниже демонстрирует, как можно либо успешно загрузить файл, либо обработать ошибку таймаута через 5 секунд. Обратите внимание, что при таймауте обещание fetch() отклоняется с исключением TimeoutError DOMException. Это позволяет коду различать таймауты (для которых, вероятно, потребуется уведомление пользователя) и явные прерывания пользователем.

const url = "video.mp4";

try {
  const res = await fetch(url, { signal: AbortSignal.timeout(5000) });
  const result = await res.blob();
  // …
} catch (err) {
  if (err.name === "TimeoutError") {
    console.error("Timeout: It took more than 5 seconds to get the result!");
  } else if (err.name === "AbortError") {
    console.error(
      "Fetch aborted by user action (browser stop button, closing tab, etc.",
    );
  } else {
    // A network error, or some other problem.
    console.error(`Error: type: ${err.name}, message: ${err.message}`);
  }
}

Прерывание fetch с таймаутом или явным прерыванием

Если вы хотите прервать работу по нескольким сигналам, можно использовать AbortSignal.any() для их объединения в один сигнал. Следующий пример демонстрирует это использование fetch:

try {
  const controller = new AbortController();
  const timeoutSignal = AbortSignal.timeout(5000);
  const res = await fetch(url, {
    // This will abort the fetch when either signal is aborted
    signal: AbortSignal.any([controller.signal, timeoutSignal]),
  });
  const body = await res.json();
} catch (e) {
  if (e.name === "AbortError") {
    // Notify the user of abort.
  } else if (e.name === "TimeoutError") {
    // Notify the user of timeout
  } else {
    // A network error, or some other problem.
    console.log(`Type: ${e.name}, Message: ${e.message}`);
  }
}

Примечание: В отличие от использования AbortSignal.timeout(), нет способа определить, вызвано ли окончательное прерывание таймаутом.

Реализация API с возможностью прерывания

API, которому требуется поддержка прерывания, может принимать объект AbortSignal и использовать его состояние для запуска обработки сигнала прерывания при необходимости.

API, основанный на Promise, должен реагировать на сигнал прерывания, отклоняя любое невыполненное обещание с исключением AbortSignal прерывания (reason ). Например, рассмотрите следующий myCoolPromiseAPI, который принимает сигнал и возвращает обещание. Обещание отклоняется немедленно, если сигнал уже прерван или если обнаружено событие прерывания. В противном случае оно завершается нормально, а затем выполняет обещание.

function myCoolPromiseAPI(/* …, */ { signal }) {
  return new Promise((resolve, reject) => {
    // If the signal is already aborted, immediately throw in order to reject the promise.
    if (signal.aborted) {
      reject(signal.reason);
    }

    // Perform the main purpose of the API
    // Call resolve(result) when done.

    // Watch for 'abort' signals
    signal.addEventListener("abort", () => {
      // Stop the main operation
      // Reject the promise with the abort reason.
      reject(signal.reason);
    });
  });
}

API может быть затем использовано, как показано. Обратите внимание, что AbortController.abort() вызывается для прерывания операции.

const controller = new AbortController();
const signal = controller.signal;

startSpinner();

myCoolPromiseAPI({ /* …, */ signal })
  .then((result) => {})
  .catch((err) => {
    if (err.name === "AbortError") return;
    showUserErrorMessage();
  })
  .then(() => stopSpinner());

controller.abort();

API, которые не возвращают обещания, могут реагировать аналогичным образом. В некоторых случаях может иметь смысл игнорировать сигнал.

Спецификации

Спецификация
DOM
# interface-AbortSignal

Совместимость браузеров

Рабочий стол Мобильный
Chrome Edge Firefox Opera Safari Chrome Android Firefox для Android Opera Android Safari на IOS Samsung Internet WebView Android
AbortSignal 66 16 57 53 11.1 66 57 47 11.3 9.0 66
abort_event 66 16 57 53 11.1 66 57 47 11.3 9.0 66
abort_static 93 93 88 79 15 93 88 66 15 17.0 93
aborted 66 16 57 53 11.1 66 57 47 11.3 9.0 66
any_static 116 116 124 102 17.4 116 124 78 17.4 24.0 116
reason 98 98 97 84 15.4 98 97 68 15.4 18.0 98
throwIfAborted 100 100 97 86 15.4 100 97 69 15.4 19.0 100
timeout_static 124
103–124Всегда прерывается с AbortError по истечении времени ожидания, а не с TimeoutError.
124
103–124Всегда прерывается с AbortError по истечении времени ожидания, а не с TimeoutError.
100 110
89–110Всегда прерывается с AbortError по истечении времени ожидания, а не с TimeoutError.
16 124
103–124Всегда прерывается с AbortError по истечении времени ожидания, а не с TimeoutError.
100 82
71–82Всегда прерывается с AbortError по истечении времени ожидания, а не с TimeoutError.
16 27.0
20.0–27.0Всегда прерывается с AbortError по истечении времени ожидания, а не с TimeoutError.
124
103–124Всегда прерывается с AbortError по истечении времени ожидания, а не с TimeoutError.

См. также

  • API Fetch
  • Прерываемый Fetch Джека Арчибальда

© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API