Aufgabe 03-3a - Promise-Fehlerjagd
Lernziele
Abschnitt betitelt „Lernziele“- Du erkennst typische Async-Fehler (vergessenes
await, nie gefangene Ablehnung,tryohneawait,forEachmitasync-Funktion,catchohne Rückgabe) in fremdem Code an ihren Symptomen. - Du behebst sie begründet statt durch Herumprobieren und erklärst den Ablauf mit dem Event-Loop-Modell.
- Du sicherst eigenen asynchronen Code mit einer Checkliste systematisch ab.
- Du setzt die Biome-Regel
noFloatingPromisesein und beurteilst, welche Fehler ein Linter findet und welche nicht.
Ausgangslage
Abschnitt betitelt „Ausgangslage“Eine Ärztin behandelt nicht auf Verdacht, sondern stellt zuerst eine Diagnose: Symptom beobachten, Ursache finden, gezielt behandeln. Genau so gehst du hier mit asynchronen Fehlern um, statt so lange herumzuprobieren, bis es “irgendwie geht”.
Fehlerbehandlung in asynchronem Code ist die häufigste Stolperstelle des Jahres. Du jagst die klassischen Async-Fehlerbilder in fünf vorbereiteten Programmen, den Jagdrevieren revier1.js, revier2.js, revier3.js, revier4.js und revier5.js. Jedes hat genau einen eingebauten Fehler und läuft mit node revierN.js. Danach härtest du deine Pizzeria aus Aufgabe 03-2a ab (siehe Kapitel Asynchrones JavaScript, Einheiten 3.2 und 3.3, jeweils die Abschnitte zu den Fallen und die Stolperfallen).
In den fünf Revieren steckt jedes der folgenden Fehlerbilder genau einmal. Welches in welchem Revier steckt, findest du selbst heraus. Die Liste ist zugleich deine Fünf-Punkte-Checkliste:
- Ein
.catch()fängt den Fehler, gibt aber nichts zurück; der Folge-Code rechnet mitundefinedweiter. forEachmit einerasync-Funktion: Die Reihenfolge stimmt nicht, und niemand wartet auf das Ende.- Ein
awaitfehlt; weiterverarbeitet wird das Promise statt des Werts. try/catchsteht um den Aufruf einer Funktion, die ein Promise liefert, aber ohneawait; der Fehler fliegt amcatchvorbei.- Ein abgelehntes Promise wird nie gefangen; das Programm stirbt mit einer Unhandled Rejection.
Allgemein
Abschnitt betitelt „Allgemein“Projektordner anlegen siehe https://qiz.at/projektordner
- Lies vorher kurz https://qiz.at/assignmentsabgabe durch.
- Nur vollständige Abgaben (siehe https://qiz.at/rules) können positiv bewertet werden.
- Abgabe- und Testdetails siehe https://qiz.at/assignmentsabgabe
- Die Übung liegt als Unterordner
uebung-03-3ain deinem Jahres-RepositorySJ26_27_4AHITM_SEW_<Benutzername>_exercises. Darin liegen die reparierten Reviere alsrevierN-fixed.jsund eine Dateifehlerjagd.mdmit Symptomen, Ursachen und Erklärungen. Die Änderungen an der Pizzeria aus Aufgabe 03-2a committest du dort als eigenen Commit. Du arbeitest allein.
Wesentlich_überwiegend
Abschnitt betitelt „Wesentlich_überwiegend“Aufgabe
Abschnitt betitelt „Aufgabe“- Führ die fünf Reviere zunächst nur aus und notiere pro Revier das Symptom in einem Satz (was ist an der Ausgabe falsch oder verdächtig?), noch ohne in den Code zu sehen.
- Für die Reviere 1, 2 und 3: Ordne jedem sein Fehlerbild aus der Liste zu, nenne die Ursache in einem Satz, behebe sie mit einer kleinen Änderung in
revierN-fixed.jsund notiere die neue Ausgabe. - Beim Revier mit
try/catch: Erklär schriftlich, warum dercatch-Block nie läuft. Wann verlässt die Ausführung dentry-Block, wann scheitert das Promise?
Tipp: Zuerst das Symptom, dann der Code: Wer sofort in den Code schaut, trainiert nicht das Erkennen.
[object Promise]oderPromise { <pending> }in einer Ausgabe heißt fast immer: Hier fehlt einawait. Der Stacktrace einer Unhandled Rejection zeigt die Stelle, an der der Fehler geworfen wurde, nicht die, an der er hätte gefangen werden müssen. Den Exit-Code zeigt in der Git Bashecho $?, in PowerShell$LASTEXITCODE;0heißt “alles in Ordnung”.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
- für alle fünf Reviere das Symptom vor dem Codeblick notiert ist.
- den Revieren 1 bis 3 das richtige Fehlerbild zugeordnet ist, die Ursache korrekt benannt ist und die reparierten Fassungen ohne Absturz das richtige Ergebnis liefern.
- die Erklärung zu
try/catchohneawaitden zeitlichen Ablauf benennt (Block verlassen, Promise scheitert später).
Wie unter Allgemein.
Wesentlich_vollständig
Abschnitt betitelt „Wesentlich_vollständig“Für alle, die in der Einheit mit den Schritten oben fertig sind bzw. optional (= freiwillig), wenn du in der Einheit nicht fertig wirst.
Aufgabe
Abschnitt betitelt „Aufgabe“Erweitere (siehe Erweitern in https://qiz.at/rules) den vollständigen Teil der vorherigen Stufe dieser Datei (ändere oder lösche nur, was für diese Aufgabe unbedingt notwendig ist):
- Für die Reviere 4 und 5 genauso: Fehlerbild, Ursache, kleine Behebung, neue Ausgabe.
- Beim Revier mit
forEach: Bau es so um, dass die Bestellungen wirklich der Reihe nach zubereitet werden und “Alle Bestellungen bearbeitet” erst danach erscheint. Erklär den Unterschied zur Fassung mitforEach. - Geh deine Pizzeria aus Aufgabe 03-2a mit der Fünf-Punkte-Checkliste durch: Behebe, was du findest, und notiere für jeden der fünf Punkte, wo du nachgesehen hast.
Tipp:
forEachruft die Funktion für jedes Element auf und wartet nie auf ihr Promise; welche Schleife wartet, zeigt Einheit 3.3 im Abschnitt “await in Schleifen”. Eincatchist auch eine Rückgabe: Was es zurückgibt, ist der neue Wert der Kette.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
- den Revieren 4 und 5 das richtige Fehlerbild zugeordnet ist und beide danach korrekt laufen.
- das
forEach-Revier die Bestellungen der Reihe nach abarbeitet und der Unterschied erklärt ist. - die Pizzeria nachweislich mit allen fünf Punkten der Checkliste geprüft ist und Funde behoben sind.
Wie unter Allgemein.
PlusPlus Aufgabe
Abschnitt betitelt „PlusPlus Aufgabe“Für alle, die in der Einheit mit den Schritten oben fertig sind bzw. optional (= freiwillig), wenn du in der Einheit nicht fertig wirst.
Aufgabe
Abschnitt betitelt „Aufgabe“Erweitere (siehe Erweitern in https://qiz.at/rules) den vollständigen Teil der vorherigen Stufe dieser Datei (ändere oder lösche nur, was für diese Aufgabe unbedingt notwendig ist):
- Verankere eine Regel in der Pizzeria: Jede
async-Funktion, die das Hauptprogramm aufruft, behandelt Fehler entweder selbst oder dokumentiert im Kommentar, dass der Aufrufer fangen muss. Kein stilles Verschlucken, nirgends. - Konstruiere ein kleines Programm mit einem Floating Promise: Eine
async-Funktion wird aufgerufen, ihr Ergebnis ignoriert, und sie scheitert erst nach einer kurzen Wartezeit. Dokumentiere zwei Fälle: ohne weitere Maßnahmen (In welcher Reihenfolge erscheinen deine “fertig”-Meldung und der Fehler? Zeigt die Fehlermeldung, wo dasawaitfehlt?) und mit einem globalen Handler, wie ihn manche Frameworks setzen:process.on("unhandledRejection", () => {});ganz oben. Weise nach, dass der Fehler dann spurlos verschwindet (etwa über ein leeres Fehlerprotokoll und den Exit-Code). - Zeig zwei Gegenmittel: das
awaitmittry/catchund, für bewusst nebenläufige Aufrufe, ein angehängtes.catch()mit Protokollierung.
Tipp: Halte die Wartezeit kurz (10 bis 50 ms) und gib nach dem Aufruf sofort “fertig” aus, dann siehst du die Reihenfolge deutlich.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
- die Regel an jeder betroffenen Funktion umgesetzt ist.
- beide Fälle mit Ausgabe und Exit-Code dokumentiert und analysiert sind.
- beide Gegenmittel gezeigt sind und den Fehler sichtbar machen.
Wie unter Allgemein.
MandalorianPlus Aufgabe
Abschnitt betitelt „MandalorianPlus Aufgabe“Für alle, die in der Einheit mit den Schritten oben fertig sind bzw. optional (= freiwillig), wenn du in der Einheit nicht fertig wirst.
Aufgabe
Abschnitt betitelt „Aufgabe“Erweitere (siehe Erweitern in https://qiz.at/rules) den vollständigen Teil der vorherigen Stufe dieser Datei (ändere oder lösche nur, was für diese Aufgabe unbedingt notwendig ist):
- Lass Biome nach solchen Fehlern suchen. Leg die fünf Original-Reviere, deine reparierten Fassungen und dein Programm aus der vorigen Stufe in
uebung-03-3a(mit"type": "module"in derpackage.json), installiere Biome mitnpm install --save-dev --save-exact @biomejs/biomeund erzeuge mitnpx @biomejs/biome initeinebiome.json. - Führ
npx @biomejs/biome lint .aus. Meldet Biome deine Floating Promises? Schalte dann die RegelnoFloatingPromisesein (Gruppenursery, unterlinter.rulesder Eintrag"nursery": { "noFloatingPromises": "error" }) und führ den Befehl erneut aus. - Beurteile die Meldungen: Welche der fünf Fehler findet die Regel, welche nicht, und warum? Warum meldet sie in jedem Original-Revier auch den Aufruf in der letzten Zeile, oft sogar in deinen reparierten Fassungen? Wie bringst du diese Meldung begründet zum Verschwinden? Lies dazu die Biome-Dokumentation zu noFloatingPromises.
- Schreib den Merkzettel “Async-Fehler: die Klassiker” für deine Klasse: je Fehlerbild eine Zeile Symptom und eine Zeile Gegenmittel, höchstens eine halbe Seite.
Tipp: Biome meldet auch anderes, zum Beispiel unbenutzte Parameter. Für diese Stufe zählen nur die Meldungen mit
lint/nursery/noFloatingPromises. Einawaitauf oberster Ebene braucht"type": "module";npm init -yträgt"commonjs"ein.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
- die Regel eingeschaltet ist und ihre Funde mit den fünf Revieren verglichen sind.
- die Meldung zum letzten Aufruf erklärt und begründet behoben ist.
- der Merkzettel knapp und vollständig ist.
Wie unter Allgemein.
Wissenscheck
Abschnitt betitelt „Wissenscheck“- Woran erkennst du in einer Ausgabe ein vergessenes
await? - Warum fängt ein
try/catchohneawaitden Fehler einerasync-Funktion nicht? - Was ist ein Floating Promise, und warum ist es gefährlich, auch wenn Node.js das Programm beim Fehler beendet?
- Warum ist
forEachmitasync-Callbacks eine Falle, und was ist der Ersatz? - Was muss ein
.catch()tun, damit der Folge-Code nicht mitundefinedweiterrechnet?
Zeit dafür
Abschnitt betitelt „Zeit dafür“Durchschnittlich bis Wesentlich_vollständig: ca. 100 min
Autoren
Abschnitt betitelt „Autoren“- Oliver Maurhart (MAO)
- Michael Gabriel (GAM)
CC-BY-SA