Die abort() Methode des AbortController ist ein zentraler Bestandteil moderner Webentwicklung, der präzise Kontrolle über asynchrone Prozesse ermöglicht. Diese Methode sendet ein Abbruchsignal an alle verbundenen Operationen, wodurch Netzwerkanfragen, Dateiübertragungen oder andere langläufige Prozesse elegant beendet werden können. Als effektives Werkzeug zur Ressourcenoptimierung verhindert sie unnötige Verarbeitung und trägt zu einer verbesserten Anwendungsperformance bei.

Einführung

Die abort() Methode des AbortController wird aufgerufen, um das Abbruchsignal an alle Operationen zu senden, die das zugehörige AbortSignal beobachten.

Syntax

Die Syntax sieht wie folgt aus.

Syntax
const controller = new AbortController();
controller.abort([reason]);

Parameter

  • reason: (Optional) Ein beliebiger Wert, der angibt, warum die Operation abgebrochen wurde. Dieser Wert wird der reason Eigenschaft des AbortSignal Objekts zugewiesen und steht der abgebrochenen Operation zur Verfügung. Wenn nicht angegeben, ist der reason ein DOMException mit dem Namen AbortError.

Rückgabewert

undefined

Funktionsweise

Wenn abort() aufgerufen wird:

  1. Die aborted Eigenschaft des zugehörigen AbortSignal wird auf true gesetzt.
  2. Das abort Ergebnis wird auf dem AbortSignal ausgelöst. Wenn ein onabort Handler für das Signal registriert wurde, wird dieser ausgeführt.
  3. Asynchrone Operationen, die dieses Signal beobachten (z.B. ein fetch Aufruf), werden abgebrochen. Typischerweise führt dies dazu, dass die Promise der Operation mit einem DOMException names AbortError rejected wird.

Einmal abgebrochen, kann ein AbortSignal nicht “un-abgebrochen” werden. Um eine neue abbrechbare Operation zu starten, muss ein neuer AbortController erstellt werden.

Beispiel 1

In diesem Beispiel bauen wir eine einfache HTML-Datei auf, welche per JavaScript Daten laden soll. Dabei werden wir die abort() Methode verwenden, um eine Anfrage abzubrechen.

JavaScript Beispiel 1
<!DOCTYPE html>
<html>
<head>
    <title>AbortController - Einfaches Fetch-Beispiel</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
    
    <button id="fetch_button">Daten laden</button>
    <button id="cancel_button">Laden abbrechen</button>
    
    <div id="output"></div>
    
    <script>
        const buttonFetch = document.getElementById("fetch_button");
        const buttonCancel = document.getElementById("cancel_button");
        const outputContainer = document.getElementById("output");
        
        let controller;
        
        buttonFetch.addEventListener("click", async () => {
            
            // Erstelle neuen AbortController
            controller = new AbortController();
            const signal = controller.signal;
            
            outputContainer.textContent = "Lade Daten ...";
            buttonCancel.disabled = false;
            buttonFetch.disabled = true;
            
            try {
                const response = await fetch("https://jsonplaceholder.typicode.com/todos/1?_delay=5000", { signal });
                
                if (!response.ok) {
                    throw new Error(`HTTP-Fehler. Status: ${response.status}`);
                }
                
                const data = await response.json();
                outputContainer.textContent = `Daten geladen: ${JSON.stringify(data)}`;
            } catch (error) {
                if (error.name === "AbortError") {
                    outputContainer.textContent = "Fetch-Anfrage wurde abgebrochen";
                    console.log("Fetch abgebrochen");
                } else {
                    outputContainer.textContent = `Fehler beim Laden: ${error.message}`;
                    console.log("Fetch Fehler:", error);
                }
            } finally {
                buttonCancel.disabled = true;
                buttonFetch.disabled = false;
            }
            
        });
        
        buttonCancel.addEventListener("click", () => {
            if (controller) {
                controller.abort();
                console.log("Abbruch angefordert");
            }
        });
        
        buttonCancel.disabled = true;
    </script>
    
</body>
</html>

Was haben wir als Ergebnis? Zwei Buttons im Browser und unseren Container, welcher verschiedene Zustände als Text ausgibt.

Wenn wir auf den Button “Daten laden” klicken und, während Daten geladen werden, auf den Button “Laden abbrechen” klicken, sehen wir dass unser Request abgebrochen wird.

Web API - AbortController - abort() Methode Beispiel 1

Wenn wir den Request neustarten und diesen nicht abbrechen, werden die Daten regulär geladen.

Web API - AbortController - abort() Methode Beispiel 2

Beispiel 2

Im nächsten Beispiel bauen wir eine HTML-Datei mit JavaScript auf, welche fetch Funktion (Fetch API) verwendet, um Anfragen mit einer bestimmten Verzögerung zu starten.

Wir verwenden Timeout und AbortController, um eine Anfrage abzubrechen, falls diese länger, als die übergebe Anzahl von Millisekunden dauert.

JavaScript Beispiel 2
<!DOCTYPE html>
<html>
<head>
    <title>AbortController - Beispiel 2</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
    
    <h1>Beispiel: Fetch von Daten mit Timeout</h1>
    <p>Öffne die Entwicklertools, um die Ausgabe zu sehen.</p>
    
    <script>
        async function fetchDataWithTimeout(url, timeoutMilliseconds) {
            const controller = new AbortController();
            const signal = controller.signal;
            
            const timeoutId = setTimeout(() => {
                controller.abort(new Error("Timeout überschritten"));
            }, timeoutMilliseconds);
            
            try {
                console.log(`Starte Fetch für: ${url}`);
                const response = await fetch(url, { signal, cache: "no-store" });
                
                // Wenn der Fetch erfolgreich war, bevor der Timeout eintritt
                clearTimeout(timeoutId);
                
                if (!response.ok) {
                    throw new Error(`HTTP Fehler! Status: ${response.status}`);
                }
                
                const data = await response.json();
                console.log("Daten erfolgreich geladen:", data);
                
                return data;
            } catch (error) {
                if (error.name === "AbortError") {
                    console.log("Fetch abgebrochen");
                    console.log("Grund:", signal.reason);
                } else {
                    console.log("Anderer Fehler:", error);
                }
                
                // Wichtig: clearTimeout auch im Fehlerfall,
                // falls der Fehler nicht durch den Timeout ausgelöst wurde
                // und der Timeout noch laufen könnte
                clearTimeout(timeoutId);
                throw error;
            }
        }
        
        // Verwendung
        fetchDataWithTimeout("https://dummyjson.com/products/?limit=10&delay=3000", 2000)
            .then(data => console.log("Verarbeitet:", data))
            .catch(error => console.log("Endgültiger Fehler im Aufrufer gefangen."));
            
        fetchDataWithTimeout("https://dummyjson.com/posts/?limit=5&delay=1000", 2000)
            .then(data => console.log("Verarbeitet (Album):", data))
            .catch(error => console.log("Endgültiger Fehler im Aufrufer gefangen (Album)"));
    </script>
    
</body>
</html>

Wenn wir nun diese Datei im Browser öffnen und in die Konsole hineinschauen, werden wir feststellen, dass ein Request korrekt verarbeitet wurde und der andere in einen Fehler hineingelaufen ist.

Web APIs - AbortController - abort() Methode Beispiel 2

Was passiert nun schrittweise in diesem Beispiel?

JavaScript
fetchDataWithTimeout("https://dummyjson.com/products/?limit=10&delay=3000", 2000)
fetchDataWithTimeout("https://dummyjson.com/posts/?limit=5&delay=1000", 2000)
  • Beide Requests laufen gleichzeitig an
  • Timeout ist bei beiden 2000 ms (2 Sekunden)
  • Verzögerungen
    • Produkte: 3000 ms (3 Sekunden)
    • Posts: 1000 ms (1 Sekunde)

Das sehen wir auch an den Logs.

Logs
Starte Fetch für: https://dummyjson.com/products/?limit=10&delay=3000
Starte Fetch für: https://dummyjson.com/posts/?limit=5&delay=1000

Die nächsten Logs (3 und 4) zeigen, dass bestimmte Daten verarbeitet worden sind.

Logs
Daten erfolgreich geladen: {posts: Array(5), total: 251, skip: 0, limit: 5}
Verarbeitet (Posts): {posts: Array(5), total: 251, skip: 0, limit: 5}
  • Der posts Request mit 1s Verzögerung wird rechtzeitig fertig.
  • Im try Block von fetchDataWithTimeout:
    • clearTimeout wird aufgerufen, da Antwort rechtzeitig kam
    • response.ok ist true
    • Die Daten werden erfolgreich geparst
  • Das Ergebnis wird im .then() des Aufrufers ausgegeben.
  • Keine Fehler, alles sauber.
Logs
Anderer Fehler: Error: Timeout überschritten 
at beispiel_2.html:19:22
  • Der products Request mit 3s Verzögerung überschreitet den Timeout von 2s.
  • Nach 2 Sekunden wird controller.abort() aufgerufen.
  • Im catch Block der Funktion wird der Fehler erkannt, hier aber nicht als AbortError, sondern als allgemeiner Fehler mit der Nachricht Timeout überschritten.
  • Dieser Fehler wird geloggt.
  • clearTimeout wird trotzdem ausgeführt.
  • Fehler wird weitergeworfen (throw error).
Logs
Endgültiger Fehler im Aufrufer gefangen.
  • Im .catch() des Aufrufers wird der Fehler aus dem products Fetch gefangen.
  • Dort wird eine einfache Meldung ausgegeben.
/ Weiter

Zurück zu Abortcontroller

Zur Übersicht