Aufgabe 04-1a - Parallel oder nacheinander?
Lernziele
Abschnitt betitelt „Lernziele“- Du koordinierst mehrere Abläufe mit
Promise.all,Promise.allSettledundPromise.raceund begründest die Wahl fachlich. - Du belegst Entscheidungen für oder gegen gleichzeitiges Starten mit Messwerten.
- Du baust einen Timeout und erklärst, warum er die Arbeit nicht abbricht.
- Du grenzt asynchrones Warten von echter Parallelität mit Workern ab.
Ausgangslage
Abschnitt betitelt „Ausgangslage“Aus der Pizzeria wird ein Betrieb: Fünf Bestellungen kommen gleichzeitig herein. Backt die Küche eine nach der anderen oder alle auf einmal? Was passiert mit dem ganzen Tisch, wenn eine Pizza verbrennt? Und wie lange wartet ein ungeduldiger Kunde?
Du misst den Unterschied zwischen nacheinander und gleichzeitig, schreibst einen Küchenbericht mit Einzelauswertung und baust einen Timeout (siehe Kapitel Nebenläufigkeit II: Koordination, Einheit 4.1; für die Stufe MandalorianPlus auch Einheit 4.2). Alles landet in kitchen.ts; die Funktion orderPizza(topping) baust du nach dem Muster deiner Pizzeria aus Aufgabe 03-2a: rund 300 ms Backzeit, in 20 Prozent der Fälle throw new Error("<topping>: burned!").
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-04-1ain deinem Jahres-RepositorySJ26_27_4AHITM_SEW_<Benutzername>_exercises, eingerichtet wie in Aufgabe 03-2a ("type": "module", Skriptedevundtypecheck). Messwerte und schriftliche Antworten stehen als Kommentar inkitchen.ts. Du arbeitest allein.
Wesentlich_überwiegend
Abschnitt betitelt „Wesentlich_überwiegend“Aufgabe
Abschnitt betitelt „Aufgabe“- Fünf Bestellungen nacheinander (Schleife mit
await): Gesamtdauer mitperformance.now()messen und notieren. - Fünf Bestellungen gleichzeitig (
Promise.allüberorders.map(...)): Gesamtdauer messen. Erklär das Verhältnis der beiden Zeiten in zwei Sätzen. - Provozier eine verbrannte Pizza und beobachte:
Promise.allreißt alle Bestellungen mit in den Fehlerfall, auch die gelungenen. - Ersetz
Promise.alldurchPromise.allSettledund gib einen Bericht aus, etwa4 delivered, 1 burned, mit den Gründen der fehlgeschlagenen Bestellungen. - Begründe in zwei Sätzen fachlich, warum hier
allSettleddas richtige Werkzeug ist und wann dagegenallrichtig wäre.
Tipp: Damit du die verbrannte Pizza nicht dem Zufall überlassen musst, gib
orderPizzawie in Aufgabe 03-2a eine eigene Zufallsfunktion mit.allSettledliefert pro Eintrag ein Objekt mitstatus; der Grund eines Fehlschlags steht inreason. Das Kriterium fürallgegenallSettledsteht in Einheit 4.1 als Merksatz.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
- beide Messwerte notiert sind und das Verhältnis mit dem langsamsten Promise erklärt ist.
- der Fehlerfall von
Promise.allnachgewiesen ist. - der Bericht mit
allSettledstimmt, die Gründe nennt und die Wahl fachlich begründet ist. kitchen.tsstrikt ohne Fehler und ohneanykompiliert.
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):
- Implementier
withTimeout<T>(promise: Promise<T>, milliseconds: number): Promise<T>mitPromise.race: Dauert der Vorgang länger, scheitert er mit"too slow, order canceled". - Teste mit einem Timeout deutlich über und deutlich unter der typischen Backzeit; beide Fälle sind im Log nachweisbar.
- Erklär in zwei Sätzen, was mit der Pizza passiert, die das Rennen verloren hat, und wie sich
AbortControllerdavon unterscheidet.
Tipp: Der Timer-Teil von
withTimeoutist ein Promise, das nie erfüllt wird; sein Typ istPromise<never>. Einheit 4.1 zeigt das Muster.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
withTimeoutgenerisch typisiert ist und in beiden Testfällen das erwartete Ergebnis liefert.- die Erklärung nennt, dass der Verlierer weiterläuft, und dass
AbortControllerdie Arbeit wirklich beendet.
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):
- Die Küche hat nur zwei Öfen. Schreib
runWithLimit(tasks, limit), das höchstenslimitBestellungen zugleich backt; die übrigen warten, bis ein Ofen frei wird. - Miss den Ansturm mit
limit1, 2 und 5 und erklär die drei Werte mit der Zahl der “Runden”, die die Küche braucht. - Nenn eine reale Situation, in der genau diese Begrenzung nötig ist, und begründe sie.
Tipp: Übergib keine Promises, sondern Funktionen, die ein Promise liefern (
() => orderPizza(topping)); sonst laufen alle Bestellungen schon beim Anlegen der Liste los.
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
- nie mehr als
limitBestellungen gleichzeitig laufen und alle Ergebnisse ankommen. - die drei Messwerte notiert und mit den Runden erklärt sind.
- die reale Situation stichhaltig ist.
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):
- Bau in einer zweiten Datei
blocking-demo.tseine bewusst teure synchrone Funktion, etwa eine naive rekursive Fibonacci-Berechnung mitnum 40, und starte dazu eine “Uhr” (setInterval, alle 100 ms ein Zeitstempel). Beobachte und erklär mit dem Event-Loop-Modell, warum die Uhr während der Berechnung steht. - Lagere die Berechnung in einen Worker aus (
node:worker_threads) und weise nach, dass die Uhr jetzt durchläuft. - Beurteile in drei Sätzen den Unterschied zwischen “asynchron” (Warten überbrücken) und “echt parallel” (gleichzeitig rechnen): Wofür genügt der Event Loop, wofür nicht?
Tipp: Miss die Abstände zwischen zwei Uhr-Ticks, dann siehst du den Aussetzer als Zahl. Für
npm run typecheckbraucht der Import ausnode:worker_threadsdie Typen von Node.js:npm install --save-dev @types/nodeund in dertsconfig.json"types": ["node"].
Bewertungskriterien
Abschnitt betitelt „Bewertungskriterien“Vollständig, wenn:
- der Aussetzer der Uhr gemessen und mit dem Event-Loop-Modell erklärt ist.
- die Variante mit Worker nachweislich ohne Aussetzer läuft und dasselbe Ergebnis liefert.
- die Beurteilung Warten und Rechnen richtig zuordnet.
Wie unter Allgemein.
Wissenscheck
Abschnitt betitelt „Wissenscheck“- Wovon hängt die Gesamtdauer von
Promise.allab? - Nach welchem fachlichen Kriterium wählt man zwischen
allundallSettled? - Was liefert
allSettledpro Eintrag, und wie unterscheidet man Erfolg von Fehlschlag? - Warum stottert die Uhr bei schwerer synchroner Rechenarbeit, obwohl
setInterval“asynchron” ist? - Worüber kommunizieren Worker mit dem Hauptthread, und was teilen sie nicht?
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