Zum Inhalt springen

Aufgabe 06 - Promise-Fehlerjagd

Zu Zen-Modus wechseln

Fehlerbehandlung in asynchronem Code ist die häufigste Stolperstelle des Jahres. Sie jagen die klassischen Async-Fehlerbilder in vorbereiteten Programmen, härten danach Ihre eigene Pizzeria ab und destillieren daraus einen Merkzettel für die Klasse (siehe Kapitel Nebenläufigkeit I).

  • Kapitel Nebenläufigkeit I, Abschnitt zu den typischen Fallen; Ihre Pizzeria aus Aufgabe 05.
  • Die fünf Jagdreviere: revier1.js, revier2.js, revier3.js, revier4.js und revier5.js - kleine Programme mit je genau einem eingebauten Fehler. Jedes einzeln mit node revierN.js ausführen.
  • Sie erkennen die klassischen Async-Fehlerbilder an ihren Symptomen.
  • Sie beheben Fehler begründet statt durch Herumprobieren.
  • Sie sichern eigenen asynchronen Code systematisch ab.
  • Reproduktion: bekannte Fehlerbilder in kleinen Programmen wiedererkennen (Teil A).
  • Reorganisation und Transfer: Ursachen analysieren, Behebungen durchführen, die Checkliste auf eigenen Code übertragen (Teile B und C).
  • Reflexion, Problemlösung und Urteilsbildung: einen schwer sichtbaren Fehlerfall selbst konstruieren und Regeln ableiten (Teil D).

Die Übung ist auf etwa zwei Stunden ausgelegt. Teil D ist der Expertenteil.

Führen Sie die fünf Programme zunächst nur aus und notieren Sie pro Programm das Symptom in einem Satz (was ist an der Ausgabe falsch oder verdächtig?), noch ohne in den Code zu sehen. Typische Symptome: [object Promise] in der Ausgabe, ein Unhandled Rejection-Absturz, falsche Reihenfolgen, verschwundene Fehler, undefined in einer Rechnung.

Jetzt mit Code: Für jedes Programm Ursache finden und beheben. Die eingebauten Fehlerbilder:

  1. Ein await fehlt; weiterverarbeitet wird das Promise statt des Werts.
  2. Ein abgelehntes Promise wird nie gefangen; das Programm stirbt mit Unhandled Rejection.
  3. try/catch steht um den Aufruf einer async-Funktion, aber ohne await; der Fehler fliegt am catch vorbei. Erklären Sie schriftlich, warum (wann verlässt die Ausführung den try-Block, wann scheitert das Promise?).
  4. forEach mit einer async-Funktion: Reihenfolge falsch, Fehler verschwinden. Ersetzen Sie es durch for...of mit await und erklären Sie den Unterschied.
  5. Ein .catch() fängt den Fehler, gibt aber nichts zurück; der Folge-Code rechnet mit undefined weiter.

Je Fund: ein Satz Ursache, die Behebung als Diff-fähige Änderung.

  1. Gehen Sie Ihre Pizzeria aus Aufgabe 05 mit der Fünf-Punkte-Checkliste aus Teil B durch: Welche Fehlerbilder könnten bei Ihnen auftreten? Beheben Sie Funde.
  2. Verankern Sie eine Regel im Code: Jede exportierte async-Funktion behandelt Fehler entweder selbst oder dokumentiert im Docstring-Kommentar, dass der Aufrufer fangen muss. Kein stilles Verschlucken, nirgends.
  1. Konstruieren Sie ein kleines Programm mit einem Floating Promise: Eine async-Funktion wird aufgerufen, ihr Ergebnis ignoriert, und ein Fehler darin verschwindet ohne jede Ausgabe, während das Programm scheinbar korrekt endet. Weisen Sie das Verschwinden nach (der Fehlerpfad loggt in eine Datei oder Variable, die leer bleibt).
  2. Zeigen Sie zwei Gegenmittel: das await (mit try/catch) und, für bewusst nebenläufige Aufrufe, ein angehängtes .catch() mit Protokollierung.
  3. Recherchieren Sie, wie das Ökosystem solche Fehler maschinell findet (Stichwort: Linter-Regel no-floating-promises), und beschreiben Sie in zwei Sätzen, was die Regel erzwingt.
  4. Schreiben Sie den Merkzettel “Async-Fehler: die Klassiker” für Ihre Klasse: je Fehlerbild eine Zeile Symptom und eine Zeile Gegenmittel, maximal eine halbe Seite.
  1. Woran erkennen Sie in einer Ausgabe ein vergessenes await?
  2. Warum fängt ein try/catch ohne await den Fehler einer async-Funktion nicht?
  3. Was ist ein Floating Promise, und warum ist es gefährlicher als ein Absturz?
  4. Warum ist forEach mit async-Callbacks eine Falle, und was ist der Ersatz?
  5. Was muss ein .catch() tun, damit der Folge-Code nicht mit undefined weiterrechnet?

Die fünf reparierten Programme mit Ursachen-Sätzen, die gehärtete Pizzeria (Änderungen als eigener Commit), das Floating-Promise-Demo aus Teil D und der Merkzettel.