Aufgabe 03-2a - Promise-Werkstatt
Lernziele
Abschnitt betitelt „Lernziele“- Du erzeugst eigene Promises mit
resolve, beschreibst ihre drei Zustände und typisierst asynchrone Funktionen mitPromise<T>. - Du schreibst abhängige Abläufe mit
async/awaitund sicherst sie mittry/catch/finallyab. - Du schreibst denselben Ablauf als Promise-Kette und mit
async/awaitund vergleichst beide Schreibweisen begründet. - Du erkennst die Folgen eines vergessenen
awaitund startest unabhängige Schritte mitPromise.allgleichzeitig.
Ausgangslage
Abschnitt betitelt „Ausgangslage“Eine Pizzeria-Küche ist ein Paradebeispiel für Nebenläufigkeit: Der Teig muss gehen, bevor belegt wird, der Ofen braucht seine Zeit, und manchmal verbrennt eine Pizza. Wer das sauber steuern kann, kann später auch jeden API-Aufruf steuern.
Du baust mit Promises und async/await eine simulierte Pizzeria-Küche: asynchrone Abläufe mit Abhängigkeiten, Wartezeiten und Fehlerfällen (siehe Kapitel Asynchrones JavaScript, Einheiten 3.1 und 3.2; für die Stufen PlusPlus und MandalorianPlus auch Einheit 3.3). Alles landet in einer Datei pizzeria.ts.
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-2ain deinem Jahres-RepositorySJ26_27_4AHITM_SEW_<Benutzername>_exercises, eingerichtet wie in Aufgabe 01:package.jsonmit"type": "module"(fürawaitauf oberster Ebene) und den Skriptendev(tsx pizzeria.ts) undtypecheck, dazu dietsconfig.jsonausnpx tsc --init. Du arbeitest allein. - Schriftliche Antworten stehen als Kommentar in
pizzeria.ts.npm run typecheckmuss fehlerfrei durchlaufen. - Verkürz die Wartezeiten beim Testen auf ein Zehntel (200 ms statt 2 s), sonst wartest du mehr, als du programmierst.
Wesentlich_überwiegend
Abschnitt betitelt „Wesentlich_überwiegend“Aufgabe
Abschnitt betitelt „Aufgabe“sleep(milliseconds): Promise<void>: löst nach der Wartezeit auf, mitsetTimeoutgebaut.- Drei Küchenschritte als typisierte
async-Funktionen:makeDough()(2 s),addToppings(dough, topping)(1 s),bake(pizza)(3 s). Jede loggt Start und Ende mit Zeitstempel und reicht ein beschreibendes Objekt weiter (etwa{ step: "dough" }). bakeschlägt in 25 Prozent der Fälle fehl:throw new Error("burned!"). Der Zufall kommt ausMath.random().orderPizza(topping): führt die drei Schritte mitawaitin der richtigen Reihenfolge aus, misst die Gesamtdauer mitperformance.now()und liefert die fertige Pizza.
Tipp: Einheit 3.1 zeigt im Abschnitt “Promises: ein Platzhalter für später”, wie man
setTimeoutin ein Promise verpackt:setTimeoutbekommt als Callback genau die Funktion, die das Promise erfüllt.new Date().toISOString().slice(17, 23)liefert Sekunden und Millisekunden, das reicht für die Zeitstempel.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
pizzeria.tsstrikt ohne Fehler und ohneanykompiliert und alle asynchronen Funktionen mitPromise<T>typisiert sind.- die Schritte in der richtigen Reihenfolge laufen und die Zeitstempel es belegen.
bakein etwa einem Viertel der Läufe mitburned!scheitert und der Fehler beim Aufrufer ankommt.
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):
- Verbrannt-Behandlung in
orderPizza: Beim ersten Fehlschlag wird genau einmal neu gebacken; scheitert auch das, wird der Fehler weitergereicht, nicht verschluckt. - Ein kleines Hauptprogramm bestellt Pizzen, fängt den Fehler und meldet ihn kundenfreundlich. Ein
finallydruckt in jedem Fall die Dauer. - Teste alle drei Fälle: Erfolg, ein Fehlschlag mit erfolgreichem zweitem Versuch, zwei Fehlschläge.
Tipp: Überleg dir, welcher Aufruf von einem
try/catchumschlossen sein muss und welcher nicht, damit der zweite Fehlschlag beim Aufrufer ankommt. Stört der Zufall beim Testen, übergibbakeoptional eine eigene Zufallsfunktion (random = Math.random); im Test liefert sie dann feste Werte.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
- es genau einen Wiederholungsversuch gibt und der zweite Fehlschlag weitergereicht und vom Aufrufer kundenfreundlich gemeldet wird.
- die Dauer in jedem Fall ausgegeben wird, auch bei zwei Fehlschlägen.
- alle drei Fälle getestet 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):
- Schreib dieselbe Kette ein zweites Mal als
then-Verkettung (orderPizzaThen), inklusive des einen Wiederholungsversuchs, und teste die drei Fälle. - Vergleich beide Fassungen in zwei bis drei Sätzen: Lesbarkeit, Fehlerbehandlung, wo würdest du welche einsetzen?
- Vorhersage zuerst, schriftlich: Was passiert, wenn in
orderPizzabeim ersten Backversuch dasawaitfehlt, alsoreturn bake(...)stattreturn await bake(...)im innerentry? Wann erscheint die Dauer im Log, findet der Wiederholungsversuch noch statt, wo landet ein Verbrannt-Fehler? - Probier es mit einem Fehlschlag beim ersten Backen aus, vergleich mit deiner Vorhersage und erklär das Verhalten mit dem Event-Loop-Modell: Wann verlässt die Ausführung den
try-Block, wann scheitert das Promise?
Tipp: Ein
catchin einer Kette gibt ein neues Promise zurück, auf das die Kette wartet. Wo du es anhängst, entscheidet, welche Fehler es fängt.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
orderPizzaThensich in allen drei Fällen gleich verhält wieorderPizzaund der Vergleich begründet ist.- Vorhersage und Beobachtung zum fehlenden
awaitdokumentiert und mit dem Modell erklärt sind.
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):
- Wo hilft TypeScript, wo nicht? Weise das Ergebnis von
bake(...)ohneawaiteiner Variablen vom TypPizzazu und greif ohneawaitauf ein Feld des Ergebnisses zu. Notiere beide Compile-Meldungen und beurteile, warumreturn bake(...)aus der vorigen Stufe keine Meldung erzeugt. - Bau eine Variante, in der zwei Beläge parallel vorbereitet werden (zweimal
addToppingsgleichzeitig, gemeinsames Warten), und miss den Zeitgewinn gegenüber der Variante nacheinander.
Tipp: Das Koordinationswerkzeug für das gemeinsame Warten zeigt Einheit 3.3; die Vertiefung folgt in Aufgabe 04-1a. Ein Zeitgewinn ohne gemessenen Vergleichswert ist keine Messung.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
- beide Compile-Meldungen notiert sind und die Beurteilung zu
return bake(...)stichhaltig ist. - der Zeitgewinn der parallelen Variante gegen die Variante nacheinander gemessen und begründet ist.
Wie unter Allgemein.
Wissenscheck
Abschnitt betitelt „Wissenscheck“- In welchen drei Zuständen kann ein Promise sein, und wie oft wechselt es?
- Was liefert eine
async-Funktion immer, auch beireturn 42? - Wohin springt die Ausführung, wenn ein erwartetes Promise (
await) scheitert? - Warum pausiert
awaitnur die Funktion und nicht das Programm? - Woran erkennst du im Log, dass zwei Schritte parallel statt nacheinander liefen?
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