AbortSignal

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since March 2019.

Hinweis: Diese Funktion ist in Web Workers verfügbar.

Die AbortSignal-Schnittstelle repräsentiert ein Signalobjekt, das es Ihnen ermöglicht, mit einem asynchronen Vorgang (wie einer Fetch-Anfrage) zu kommunizieren und diesen bei Bedarf über ein AbortController-Objekt abzubrechen.

EventTarget AbortSignal

Instanzeigenschaften

Erbt auch Eigenschaften von seiner Elternschnittstelle, EventTarget.

AbortSignal.aborted Schreibgeschützt

Ein Boolean, das angibt, ob die Anfrage(n), mit der(en) das Signal kommuniziert, abgebrochen ist/sind (true) oder nicht (false).

AbortSignal.reason Schreibgeschützt

Ein JavaScript-Wert, der den Abbruchgrund angibt, sobald das Signal abgebrochen wurde.

Statische Methoden

Erbt auch Methoden von seiner Elternschnittstelle, EventTarget.

AbortSignal.abort()

Gibt eine AbortSignal-Instanz zurück, die bereits als abgebrochen gesetzt ist.

AbortSignal.any()

Gibt ein AbortSignal zurück, das abbricht, wenn eines der angegebenen Abbruchsignale abbricht.

AbortSignal.timeout()

Gibt eine AbortSignal-Instanz zurück, die nach einer bestimmten Zeit automatisch abgebrochen wird.

Instanzmethoden

Erbt auch Methoden von seiner Elternschnittstelle, EventTarget.

AbortSignal.throwIfAborted()

Wirft den Abbruch-reason des Signals, wenn das Signal abgebrochen wurde; andernfalls passiert nichts.

Ereignisse

Erbt auch Ereignisse von seiner Elternschnittstelle, EventTarget.

Dieses Ereignis kann mit addEventListener() abgehört werden oder indem ein Ereignislistener der oneventname-Eigenschaft dieser Schnittstelle zugewiesen wird.

abort

Wird aufgerufen, wenn die asynchronen Vorgänge, mit der(en) das Signal kommuniziert, abgebrochen werden. Auch über die onabort-Eigenschaft verfügbar.

Beispiele

Abbrechen einer Fetch-Operation mit einem expliziten Signal

Der folgende Ausschnitt zeigt, wie wir ein Signal verwenden könnten, um das Herunterladen eines Videos mit der Fetch API abzubrechen.

Zunächst erstellen wir einen Abbruch-Controller mit dem AbortController()-Konstruktor und holen dann eine Referenz auf sein zugehöriges AbortSignal-Objekt über die AbortController.signal-Eigenschaft.

Wenn die Fetch-Anfrage initiiert wird, übergeben wir das AbortSignal als Option in das Optionsobjekt der Anfrage (das {signal} unten). Dies verknüpft das Signal und den Controller mit der Fetch-Anfrage und ermöglicht uns, sie abzubrechen, indem wir AbortController.abort() aufrufen. Unten können Sie sehen, dass die Fetch-Operation im zweiten Ereignislistener abgebrochen wird, der ausgelöst wird, wenn der Abbruchknopf (abortBtn) geklickt wird.

Wenn abort() aufgerufen wird, lehnt das fetch()-Promise mit einer DOMException namens AbortError ab.

js
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}`);
  }
}

Wenn die Anfrage nach dem Abschluss des fetch()-Aufrufs, aber bevor der Antwortkörper gelesen wurde, abgebrochen wird, wird der Versuch, den Antwortkörper zu lesen, mit einer AbortError-Ausnahme abgelehnt.

js
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);
}

Sie können ein voll funktionsfähiges Beispiel auf GitHub finden; Sie können es auch live sehen.

Abbrechen einer Fetch-Operation mit einem Timeout

Wenn Sie die Operation bei einem Timeout abbrechen müssen, können Sie die statische Methode AbortSignal.timeout() verwenden. Diese gibt ein AbortSignal zurück, das nach einer bestimmten Anzahl von Millisekunden automatisch abgebrochen wird.

Der untenstehende Codeausschnitt zeigt, wie Sie entweder erfolgreich eine Datei herunterladen, oder einen Timeout-Fehler nach 5 Sekunden behandeln würden. Beachten Sie, dass bei einem Timeout das fetch()-Promise mit einer TimeoutError DOMException abgelehnt wird. Dies ermöglicht es dem Code, zwischen Timeouts (für die wahrscheinlich eine Benachrichtigung des Benutzers erforderlich ist) und Benutzerabbrüchen zu unterscheiden.

js
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}`);
  }
}

Abbrechen eines Fetch mit Timeout oder explizitem Abbruch

Wenn Sie aus mehreren Signalen abbrechen möchten, können Sie AbortSignal.any() verwenden, um sie in ein einziges Signal zu kombinieren. Das folgende Beispiel zeigt dies mit fetch:

js
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}`);
  }
}

Hinweis: Anders als bei der Verwendung von AbortSignal.timeout(), gibt es keine Möglichkeit festzustellen, ob der endgültige Abbruch durch einen Timeout verursacht wurde.

Implementieren einer abbrechbaren API

Eine API, die das Abbrechen unterstützen muss, kann ein AbortSignal-Objekt akzeptieren und seinen Status verwenden, um bei Bedarf das Handling von Abbruchsignalen auszulösen.

Eine auf Promise basierende API sollte auf das Abbruchsignal reagieren, indem sie ein ungelöstes Promise mit dem Abbruch-reason des AbortSignal ablehnt. Zum Beispiel kann die folgende myCoolPromiseAPI, die ein Signal annimmt und ein Promise zurückgibt, sofort abgelehnt werden, wenn das Signal bereits abgebrochen ist oder das Abbruchereignis erkannt wird. Andernfalls wird es normal abgeschlossen und das Promise wird aufgelöst.

js
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);
    });
  });
}

Die API könnte dann wie gezeigt verwendet werden. Beachten Sie, dass AbortController.abort() aufgerufen wird, um die Operation abzubrechen.

js
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();

APIs, die keine Promises zurückgeben, könnten auf ähnliche Weise reagieren. In einigen Fällen kann es sinnvoll sein, das Signal zu absorbieren.

Spezifikationen

Specification
DOM Standard
# interface-AbortSignal

Browser-Kompatibilität

BCD tables only load in the browser

Siehe auch