Aufwärmen · Aufgabe 1 von 7
Zum Aufwärmen: einfacher synchroner Code, noch nichts Asynchrones. Was gibt dieser Code aus?
function a() {
console.log('a start');
b();
console.log('a end');
}
function b() {
console.log('b');
}
a();// I1.1 · ca. 32 Min. · Aufbau
Nach dieser Lektion können Sie vorhersagen, in welcher Reihenfolge synchroner Code, Promise-Callbacks, Fortsetzungen nach await und Timer laufen, asynchrone Fehler dort abfangen, wo sie wirklich entstehen, und gezielt zwischen Promise.all und Promise.allSettled wählen.
Lektion 1 von 6 in I1 Asynchrones JavaScript
Danach können Sie
Aufwärmen · Aufgabe 1 von 7
function a() {
console.log('a start');
b();
console.log('a end');
}
function b() {
console.log('b');
}
a();Vorhersagen · Aufgabe 2 von 7
console.log('A');
setTimeout(() => console.log('B'), 0);
Promise.resolve().then(() => console.log('C'));
console.log('D');Üben · Aufgabe 3 von 7
async function run() {
console.log('run: start');
await null;
console.log('run: after await');
}
setTimeout(() => console.log('timeout'), 0);
run();
queueMicrotask(() => console.log('microtask'));
console.log('script end');Üben · Aufgabe 4 von 7
async function load() {
throw new Error('boom');
}
try {
load();
} catch (err) {
console.log('caught:', err.message);
}
console.log('done');Üben · Aufgabe 5 von 7
// ES module, so top-level await is allowed
const fetchUser = () => Promise.resolve('Ada');
const fetchPosts = () => Promise.reject(new Error('posts API down'));
const results = await Promise.____([fetchUser(), fetchPosts()]);
for (const r of results) {
if (r.status === 'fulfilled') console.log('ok:', r.value);
else console.log('failed:', r.reason.message);
}Denksport · Aufgabe 6 von 7
async function getData() {
throw new Error('offline');
}
async function load() {
try {
return getData();
} catch (err) {
return 'fallback';
}
}
load().then(
(value) => console.log('value:', value),
(err) => console.log('error:', err.message)
);Anwenden · Aufgabe 7 von 7
Prüfen Sie Ihr Ergebnis anhand dieser Liste
Lesen Sie das ausgearbeitete Beispiel und lösen Sie dann die Übungen. Ihr Code läuft in Ihrem Browser oder auf Ihrem Computer und wird nie hochgeladen.
Ausgearbeitetes Beispiel
Die Buchstaben zeigen die Reihenfolge, in der die Zeilen erscheinen. Zuerst laufen die synchronen Zeilen, A bis C, einschließlich des Starts von work() bis zu seinem await. Dann wird die Microtask-Schlange abgearbeitet: der then()-Callback, der Rest von work() und alles, worauf die Top-Level-await warten, denn ein Promise, das ohne Timer erledigt wird, wird in Microtasks erledigt. Der Task des Timers läuft zuletzt, obwohl er als Zweites eingeplant wurde.
main.js
console.log('A sync');
setTimeout(() => console.log('H timer (a task)'), 0);
Promise.resolve().then(() => console.log('D then (a microtask)'));
async function work() {
console.log('B work starts (still sync)');
await null;
console.log('E work after await (a microtask)');
}
work();
console.log('C sync, end of the first job');
// Errors: await inside try, and allSettled to keep every outcome.
const fail = (message) => Promise.reject(new Error(message));
async function load() {
try {
return await fail('offline');
} catch (err) {
return `fallback (${err.message})`;
}
}
console.log('F load:', await load());
const results = await Promise.allSettled([Promise.resolve('news'), fail('weather down')]);
console.log('G allSettled:', results.map((r) => (r.status === 'fulfilled' ? r.value : r.reason.message)));
Ausführen mit
node main.jsAusgabe
A sync
B work starts (still sync)
C sync, end of the first job
D then (a microtask)
E work after await (a microtask)
F load: fallback (offline)
G allSettled: [ 'news', 'weather down' ]
H timer (a task)Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser den JavaScript-Runner herunter (bis zu 0.1 MB) und speichert ihn im Cache. Ihr Code läuft in der eigenen Engine Ihres Browsers und bleibt auf Ihrem Gerät.
Übung 1 von 2
safeLoad(load) ruft die async-Funktion load auf und soll mit deren Wert erfüllt werden, oder mit "fallback", wenn load abgelehnt wird. Der Startcode gibt load() innerhalb des try zurück, ohne es abzuwarten, die Ablehnung rutscht also am catch vorbei. Beheben Sie das mit einem Wort.
Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser den JavaScript-Runner herunter (bis zu 0.1 MB) und speichert ihn im Cache. Ihr Code läuft in der eigenen Engine Ihres Browsers und bleibt auf Ihrem Gerät.
Führen Sie die Tests aus: safeLoad wird mit offline abgelehnt. Wann wird das Promise von load() abgelehnt: innerhalb des try oder erst, nachdem safeLoad es verlassen hat?
Das catch sieht nur eine Ablehnung, die geworfen wird, solange das try noch läuft. Welches Schlüsselwort macht aus einer Ablehnung ein throw?
return await load();
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
export async function safeLoad(load) {
try {
return await load();
} catch {
return "fallback";
}
}
Installieren Sie ECMAScript 2026 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.
main.js
export async function safeLoad(load) {
try {
return load();
} catch {
return "fallback";
}
}
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {safeLoad} from './main.js';
test('Ein load, das gelingt, liefert seinen Wert', async () => {
const got = await safeLoad(async () => 'data');
assert.equal(got, 'data', `safeLoad gab ${got}`);
});
test('Ein load, das abgelehnt wird, liefert fallback', async () => {
const got = await safeLoad(async () => {
throw new Error('offline');
}).catch((error) => `abgelehnt mit ${error.message}`);
assert.equal(got, 'fallback', `safeLoad gab: ${got}`);
});
package.json
{
"type": "module"
}
package.json sagt Node.js, dass die .js-Dateien Module sind; lassen Sie die Datei im Ordner.
Programm ausführen:
node main.jsPrüfungen ausführen (learnrun.js muss im selben Ordner liegen):
node --testlearnrun.js herunterladenÜbung 2 von 2
summarize(promises) soll auf jedes Promise warten und mit {ok, failed} erfüllt werden: ok enthält die Werte derer, die erfüllt wurden, failed die Meldungen derer, die abgelehnt wurden, beides in der Reihenfolge der Eingabe. Der Startcode benutzt Promise.all, ein einziger Fehlschlag lehnt also alles ab. Benutzen Sie den Kombinator, der nie ablehnt.
Tab rückt ein, Umschalt+Tab rückt aus. Um den Editor mit der Tastatur zu verlassen, drücken Sie Esc und dann Tab.
Beim ersten Ausführen lädt Ihr Browser den JavaScript-Runner herunter (bis zu 0.1 MB) und speichert ihn im Cache. Ihr Code läuft in der eigenen Engine Ihres Browsers und bleibt auf Ihrem Gerät.
Führen Sie die Tests aus: summarize wird mit weather down abgelehnt. Welcher Kombinator wartet auf jede Eingabe und lehnt nie ab?
Promise.allSettled liefert pro Eingabe ein Objekt: {status: "fulfilled", value} oder {status: "rejected", reason}.
Gehen Sie die Ergebnisse durch: result.value an ok anhängen oder result.reason.message an failed.
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
export async function summarize(promises) {
const results = await Promise.allSettled(promises);
const ok = [];
const failed = [];
for (const result of results) {
if (result.status === "fulfilled") ok.push(result.value);
else failed.push(result.reason.message);
}
return {ok, failed};
}
Installieren Sie ECMAScript 2026 oder neuer. Speichern Sie diese Dateien in einem Ordner, öffnen Sie dort ein Terminal und führen Sie die Befehle unten aus.
main.js
export async function summarize(promises) {
const values = await Promise.all(promises);
return {ok: values, failed: []};
}
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {summarize} from './main.js';
const fail = (message) => Promise.reject(new Error(message));
test('Alles gelingt: jeder Wert in ok', async () => {
const got = await summarize([Promise.resolve('news'), Promise.resolve('stocks')]);
assert.deepEqual(got, {ok: ['news', 'stocks'], failed: []}, `summarize gab ${JSON.stringify(got)}`);
});
test('Fehlschläge werden gemeldet, der Rest bleibt erhalten', async () => {
const got = await summarize([Promise.resolve('news'), fail('weather down'), fail('stocks down')]).catch((error) => `abgelehnt mit ${error.message}`);
assert.deepEqual(got, {ok: ['news'], failed: ['weather down', 'stocks down']}, `summarize gab ${JSON.stringify(got)}`);
});
package.json
{
"type": "module"
}
package.json sagt Node.js, dass die .js-Dateien Module sind; lassen Sie die Datei im Ordner.
Programm ausführen:
node main.jsPrüfungen ausführen (learnrun.js muss im selben Ordner liegen):
node --testlearnrun.js herunterladenlet data;
setTimeout(() => {
data = {items: [1, 2]};
}, 0);
console.log(data.items.length);
Was Node.js ausgibt
TypeError: Cannot read properties of undefined (reading 'items')Warum, und die Lösung
Ein Timer-Callback ist ein Task: Er läuft erst, nachdem das aktuelle Skript beendet ist, auch bei 0 ms Verzögerung. Wenn die letzte Zeile läuft, ist data noch undefined. Benutzen Sie die Daten innerhalb des Callbacks, oder packen Sie den Timer in ein Promise und warten Sie darauf, bevor Sie data lesen.
async function load() {
throw new Error("boom");
}
try {
load();
} catch (err) {
console.log("caught:", err.message);
}
console.log("done");
Was Node.js ausgibt
Error: boomWarum, und die Lösung
load() wirft nicht beim Aufruf: Es gibt ein abgelehntes Promise zurück, das try endet normal, „done“ erscheint, und die Ablehnung wird nie behandelt, das Programm stoppt also mit ihr. Warten Sie innerhalb des try darauf, in einer async-Funktion oder einem Modul: try { await load(); } catch (err) { … }.
const results = await Promise.all([Promise.resolve(1), Promise.reject(new Error("x failed"))]);
console.log(results);
Was Node.js ausgibt
Error: x failedWarum, und die Lösung
Promise.all lehnt mit der ersten Ablehnung ab, und ein await auf ein abgelehntes Promise wirft. Nichts fängt das hier ab, das Programm stoppt also vor console.log. Packen Sie das await in try/catch, oder benutzen Sie Promise.allSettled, wenn jeder Ausgang zählt.
JavaScript im Browser: die eigene Engine Ihres Browsers in einem abgeschotteten Worker. Syntaxfehler findet acorn 8.18.0, MIT. Lizenz und Quellcode
5 Fragen, ohne Hinweise. Ab 80 % ist die Lektion abgeschlossen.
Erledigen Sie zuerst alle Aufgaben oben, um das Abschlussquiz freizuschalten.