navigation Navigation


AbortController - abort() Methhode


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.

Inhaltsverzeichnis

    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.

    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.

    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.

    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?

    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.

    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.

    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.

    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).

    Endgültiger Fehler im Aufrufer gefangen.
    • Im .catch() des Aufrufers wird der Fehler aus dem products Fetch gefangen.
    • Dort wird eine einfache Meldung ausgegeben.