W3docs

Fetch: Abbruch

Fetch-Anfragen in JavaScript mit AbortController und AbortSignal abbrechen: Benutzeraktionen, Timeouts, mehrere Anfragen gleichzeitig und AbortError.

Sobald eine fetch()-Anfrage gestartet ist, läuft sie so lange weiter, bis der Server antwortet – selbst wenn der Benutzer die Seite verlassen hat, einen neuen Suchbegriff eingegeben hat oder das Ergebnis nicht mehr benötigt wird. Diese verschwendeten Anfragen blockieren Verbindungen, verbrauchen Akku und Bandbreite und können veraltete Ergebnisse liefern, die frische überschreiben. Die AbortController-Schnittstelle bietet eine saubere, standardisierte Möglichkeit, eine Anfrage bei Bedarf abzubrechen.

Dieses Kapitel zeigt, wie man AbortController einrichtet, auf Benutzeraktionen reagiert, Timeouts erstellt, mehrere Anfragen gleichzeitig abbricht und den resultierenden AbortError korrekt behandelt. Weitere Informationen zu fetch selbst finden Sie auf der vorherigen Seite, Fetch API.

Wie AbortController funktioniert

AbortController ist ein kleines Objekt mit einer einzigen Aufgabe: Es besitzt ein AbortSignal und kann dieses Signal in den Zustand abgebrochen versetzen. Das Signal ist der Teil, den Sie an fetch() übergeben (und an viele andere Browser-APIs, wie etwa addEventListener). Wenn Sie controller.abort() aufrufen, werden alle Operationen, die dieses Signal empfangen haben, abgebrochen.

Das Muster besteht immer aus denselben drei Schritten:

  1. Einen Controller erstellen: const controller = new AbortController().
  2. controller.signal an fetch() im Options-Objekt übergeben.
  3. controller.abort() aufrufen, wann immer Sie abbrechen möchten.

Wenn ein fetch abgebrochen wird, lehnt sein Promise mit einer DOMException ab, deren name "AbortError" ist. Deshalb überprüft jedes Beispiel unten error.name === 'AbortError' – damit Sie den absichtlichen Abbruch ignorieren können, während echte Netzwerkfehler trotzdem angezeigt werden.

Grundlegende Verwendung von AbortController

Hier ist das kleinstmögliche vollständige Beispiel. Es bricht sofort ab, damit Sie den Ablehnungspfad sehen können:

javascript— editable

Wir erstellen einen AbortController, übergeben sein signal an fetch() und rufen sofort controller.abort() auf. Da die Anfrage nie normal abgeschlossen wird, läuft .catch() und meldet den Abbruch.

Das Signal untersuchen: aborted und das abort-Ereignis

Das Signal legt seinen Zustand offen, damit anderer Code auf einen Abbruch reagieren kann. Zwei Mitglieder sind am wichtigsten:

  • signal.aborted — ein boolean, der true wird, sobald abgebrochen wurde.
  • das "abort"-Ereignis — wird auf dem Signal in dem Moment ausgelöst, in dem abort() aufgerufen wird.
javascript— editable

Das ist praktisch, wenn Sie Nicht-fetch-Arbeit haben (einen Timer, eine Animation, einen Stream-Reader), die in dem Moment stoppen soll, in dem die Anfrage abgebrochen wird.

Ein Controller, eine Verwendung. Ein Controller kann nicht zurückgesetzt werden. Sobald Sie abort() aufrufen, bleibt dieses Signal für immer abgebrochen, und jeder neue fetch(), den Sie damit starten, lehnt sofort ab. Erstellen Sie für eine neue Anfrage einen neuen AbortController.

Praktisches Beispiel: Abbruch bei einer Benutzeraktion

Der häufigste Grund für einen Abbruch ist ein Benutzer, der seine Meinung ändert – auf „Abbrechen" klickt, einen Dialog schließt oder eine neue Anfrage stellt, bevor die vorherige abgeschlossen war. Hier bricht ein Button eine laufende Anfrage ab:

<body>
  <button id="abortButton">Abort Fetch Request</button>
  <script>
    const controller = new AbortController();
    const signal = controller.signal;
    document.getElementById('abortButton').addEventListener('click', () => {
      controller.abort();
    });
    fetch('https://httpbin.org/delay/5', { signal })
      .then(response => response.json())
      .then(data => alert(
        'Data is successfully fetched! Refresh the page and try aborting.'
      ))
      .catch(error => {
        if (error.name === 'AbortError') {
          alert('Fetch request was aborted by the user');
        } else {
          alert('Fetch error: ' + error.message);
        }
      });
  </script>
</body>

Ein Klick auf den Button mit der ID abortButton bricht die laufende fetch-Anfrage ab. Der Endpunkt https://httpbin.org/delay/5 dauert absichtlich 5 Sekunden, sodass ein Klick innerhalb dieses Zeitfensters die Anfrage mit einem AbortError ablehnt.

Mehrere Anfragen gleichzeitig abbrechen

Ein einzelnes Signal kann an viele Anfragen weitergegeben werden. Ein einziger Aufruf von controller.abort() bricht sie alle ab – nützlich, wenn eine Seite eine Ansicht verlässt, die mehrere parallele Ladevorgänge gestartet hat:

javascript— editable

Da alle drei Anfragen ein Signal teilen, bricht controller.abort() sie mit einem einzigen Aufruf ab und Promise.all lehnt mit AbortError ab. Weitere Informationen zum parallelen Ausführen von Anfragen finden Sie unter Promise API.

Nach einem Timeout abbrechen

Eine sehr häufige Verwendung von AbortController besteht darin, einer Anfrage eine Frist zu setzen: Wenn der Server zu langsam ist, abbrechen und einen Fehler anzeigen, anstatt ewig zu warten.

Der manuelle Weg mit setTimeout

Sie können den Controller mit einem Timer kombinieren und mit beliebiger anderer asynchroner Logik verbinden. Hier löst ein separater Vorgang den Abbruch nach einer Sekunde aus, während der Endpunkt fünf Sekunden benötigen würde:

javascript— editable

Der fetch wird nach einer Sekunde durch den Timer abgebrochen, weit bevor der Fünf-Sekunden-Endpunkt antworten kann. Mehr über Timer erfahren Sie unter async/await.

Die Abkürzung: AbortSignal.timeout()

Moderne Browser (und Node 17.3+) liefern einen eingebauten Helfer mit, der ein Signal erstellt, das sich nach einer bestimmten Anzahl von Millisekunden selbst abbricht – kein Controller oder setTimeout erforderlich:

javascript— editable

Beachten Sie, dass ein Timeout-Abbruch mit einem TimeoutError ablehnt, nicht mit einem AbortError, sodass Sie „zu lange gedauert" von „der Benutzer hat abgebrochen" unterscheiden können. Wenn Sie sowohl ein Timeout als auch einen manuellen Abbrechen-Button benötigen, kombinieren Sie Signale mit AbortSignal.any([userSignal, AbortSignal.timeout(2000)]).

AbortError korrekt behandeln

Immer wenn Sie einen fetch abbrechen, lehnt das Promise ab. Wenn Sie dies vergessen zu behandeln, entsteht eine störende „uncaught promise rejection" in der Konsole, obwohl der Abbruch absichtlich war. Zwei Regeln halten die Dinge sauber:

  • Immer ein .catch() (oder try/catch mit await) bei einer abbrechbaren fetch-Anfrage verwenden.
  • Darin error.name überprüfen und 'AbortError' / 'TimeoutError' als erwartet behandeln – nur die anderen Fehler protokollieren oder anzeigen. Weitere Informationen zum übergeordneten Muster finden Sie unter Fehlerbehandlung mit Promises.

Fazit

AbortController ist der Standardweg, um fetch()-Anfragen in JavaScript abzubrechen. Erstellen Sie einen Controller, übergeben Sie sein signal an eine oder mehrere Anfragen und rufen Sie abort() auf, sobald die Arbeit nicht mehr benötigt wird. Sie haben benutzerausgelöste Abbrüche, manuelle und eingebaute Timeouts, das gleichzeitige Abbrechen vieler Anfragen sowie den Umgang mit dem resultierenden AbortError kennengelernt. Diese Muster halten Ihre Anwendungen reaktionsschnell und verhindern, dass sie Zeit mit Ergebnissen verschwenden, auf die niemand mehr wartet.

Übungen

Übung
Was ist der Zweck, die signal-Eigenschaft eines AbortControllers an eine fetch-Anfrage zu übergeben?
Was ist der Zweck, die signal-Eigenschaft eines AbortControllers an eine fetch-Anfrage zu übergeben?
Was this page helpful?