Aufwärmen · Aufgabe 1 von 7
Zum Aufwärmen, aus Lektion I3.5: eine leere JSON-Datei. Was gibt dieser Code aus?
try {
JSON.parse("");
} catch (error) {
console.log(error.name);
}// I4.1 · ca. 38 Min. · Aufbau
Nach dieser Lektion lassen Sie Ihre Funktionen mit einem Error laut scheitern, behandeln die Fehler, die Sie erwarten, und lassen die anderen durch.
Lektion 1 von 5 in I4 Fehler, Debugging und Tests
Danach können Sie
Aufwärmen · Aufgabe 1 von 7
try {
JSON.parse("");
} catch (error) {
console.log(error.name);
}Vorhersagen · Aufgabe 2 von 7
try {
console.log("A");
throw new Error("B");
console.log("C");
} catch (error) {
console.log(error.message);
} finally {
console.log("D");
}
console.log("E");Üben · Aufgabe 3 von 7
if (error ____ RangeError) console.log("range");Üben · Aufgabe 4 von 7
function load() {
try {
return "data";
} finally {
console.log("cleanup");
}
}
console.log(load());Üben · Aufgabe 5 von 7
function parse(text) {
try {
return JSON.parse(text).items.length;
} catch (error) {
if (error instanceof SyntaxError) return 0;
throw error;
}
}
try {
console.log(parse("{}"));
} catch (error) {
console.log("outer:", error.name);
}Denksport · Aufgabe 6 von 7
function check() {
try {
throw new Error("broken");
} catch (error) {
return "caught " + error.message;
} finally {
return "finally wins";
}
}
console.log(check());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
parseAge wirft einen TypeError für Text, der keine ganze Zahl ist, und einen RangeError für ein Alter außerhalb des Bereichs. Die Schleife fängt jeden Fehler, eine schlechte Eingabe stoppt die anderen also nicht, und finally meldet jede Eingabe. readSettings behandelt kaputtes JSON mit Standardwerten und wirft jeden anderen Fehler weiter.
main.js
function parseAge(text) {
const age = Number(text);
if (!Number.isInteger(age)) throw new TypeError(`Not a whole number: "${text}"`);
if (age < 0 || age > 150) throw new RangeError(`Out of range: ${age}`);
return age; // only reached when both checks pass
}
for (const input of ["42", "abc", "-3"]) {
try {
console.log("age", parseAge(input));
} catch (error) {
console.log(error.name + ": " + error.message);
} finally {
console.log("checked", input);
}
}
function readSettings(text) {
try {
return JSON.parse(text);
} catch (error) {
if (error instanceof SyntaxError) return {}; // broken JSON: use defaults
throw error; // anything else is not ours to handle
}
}
console.log(readSettings('{"theme": "dark"}'), readSettings("{oops"));
Ausführen mit
node main.jsAusgabe
age 42
checked 42
TypeError: Not a whole number: "abc"
checked abc
RangeError: Out of range: -3
checked -3
{ theme: 'dark' } {}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 3
parsePrice(text) macht aus Text wie "12.50" eine Zahl. Für Text, der keine Zahl ist, oder für leeren Text muss es einen TypeError mit der Meldung Not a price: "…" (der Text in Anführungszeichen) werfen, für eine negative Zahl einen RangeError. Der Starter gibt zurück, was Number liefert, schlechte Eingaben rutschen also als NaN oder 0 durch.
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.
Number("abc") ist NaN und Number("") ist 0: Prüfen Sie beides, bevor Sie zurückgeben.
Number.isNaN(price) und text.trim() === "" finden die beiden schlechten Fälle.
throw new TypeError(`Not a price: "${text}"`)
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
export function parsePrice(text) {
const price = Number(text);
if (text.trim() === "" || Number.isNaN(price)) throw new TypeError(`Not a price: "${text}"`);
if (price < 0) throw new RangeError(`Negative price: ${price}`);
return price;
}
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 function parsePrice(text) {
return Number(text);
}
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {parsePrice} from './main.js';
test('12.50 ist 12.5', () => {
assert.equal(parsePrice('12.50'), 12.5, 'parsePrice("12.50") sollte 12.5 sein');
});
test('abc wirft einen TypeError mit dem Text in der Meldung', () => {
assert.throws(() => parsePrice('abc'), {name: 'TypeError', message: 'Not a price: "abc"'}, 'parsePrice("abc") sollte TypeError: Not a price: "abc" werfen');
});
test('ein leerer Text wirft einen TypeError, nicht 0', () => {
assert.throws(() => parsePrice(''), {name: 'TypeError'}, 'parsePrice("") sollte einen TypeError werfen, aber Number("") ist 0');
});
test('ein negativer Preis wirft einen RangeError', () => {
assert.throws(() => parsePrice('-1'), {name: 'RangeError'}, 'parsePrice("-1") sollte einen RangeError werfen');
});
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 3
loadCart(text) liest einen als JSON gespeicherten Warenkorb: ein Array von Artikeln. Kaputtes JSON soll einen leeren Warenkorb ergeben, aber gültiges JSON, das kein Array ist, ist ein Bug an anderer Stelle und muss den TypeError Cart must be an array werfen. Das catch im Starter verschluckt jeden Fehler, dieser TypeError erreicht den Aufrufer also nie. Behandeln Sie nur SyntaxError.
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.
Geben Sie dem catch-Block einen Namen für den Fehler, damit Sie ihn ansehen können.
error instanceof SyntaxError ist nur für kaputtes JSON true.
Für jeden anderen Fehler: throw error;
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
export function loadCart(text) {
try {
const cart = JSON.parse(text);
if (!Array.isArray(cart)) throw new TypeError("Cart must be an array");
return cart;
} catch (error) {
if (error instanceof SyntaxError) return [];
throw error;
}
}
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 function loadCart(text) {
try {
const cart = JSON.parse(text);
if (!Array.isArray(cart)) throw new TypeError("Cart must be an array");
return cart;
} catch {
return [];
}
}
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {loadCart} from './main.js';
test('ein gespeichertes Array kommt zurück', () => {
const cart = loadCart('[{"id": 1}]');
assert.deepEqual(cart, [{id: 1}], `loadCart ergab ${JSON.stringify(cart)}`);
});
test('kaputtes JSON ergibt einen leeren Warenkorb', () => {
const cart = loadCart('[{"id": 1');
assert.deepEqual(cart, [], `loadCart ergab ${JSON.stringify(cart)}`);
});
test('ein Objekt statt eines Arrays wirft den TypeError', () => {
assert.throws(() => loadCart('{"id": 1}'), {name: 'TypeError', message: 'Cart must be an array'}, 'loadCart sollte den TypeError nicht verschlucken');
});
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 3 von 3
runLocked(lock, task) setzt lock.busy auf true, führt task() aus und gibt dessen Ergebnis zurück. Danach muss lock.busy wieder false sein, auch wenn task wirft; der Fehler selbst muss den Aufrufer trotzdem erreichen. Der Starter entsperrt nur nach einer erfolgreichen task, eine fehlgeschlagene task lässt die Sperre also für immer belegt.
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.
Welcher Block läuft sowohl nach Erfolg als auch nach einem Fehler?
Ein catch brauchen Sie hier nicht: try...finally lässt den Fehler durch.
try { return task(); } finally { lock.busy = false; }
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
export function runLocked(lock, task) {
lock.busy = true;
try {
return task();
} finally {
lock.busy = false;
}
}
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 function runLocked(lock, task) {
lock.busy = true;
const result = task();
lock.busy = false;
return result;
}
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {runLocked} from './main.js';
test('gibt das Ergebnis zurück und entsperrt', () => {
const lock = {busy: false};
assert.equal(runLocked(lock, () => 42), 42, 'runLocked sollte zurückgeben, was die task zurückgibt');
assert.equal(lock.busy, false, 'lock.busy sollte nach der task false sein');
});
test('die task sieht die Sperre als belegt', () => {
const lock = {busy: false};
assert.equal(runLocked(lock, () => lock.busy), true, 'lock.busy sollte true sein, während die task läuft');
});
test('eine fehlschlagende task entsperrt trotzdem, und ihr Fehler erreicht den Aufrufer', () => {
const lock = {busy: false};
assert.throws(() => runLocked(lock, () => { throw new Error('disk full'); }), {message: 'disk full'}, 'der Fehler der task sollte den Aufrufer erreichen');
assert.equal(lock.busy, false, 'lock.busy sollte nach einer fehlgeschlagenen task false sein');
});
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 herunterladenfunction findUser(id) {
throw "User " + id + " not found";
}
try {
findUser(7);
} catch (error) {
console.log(error.message.toUpperCase());
}
Was Node.js ausgibt
TypeError: Cannot read properties of undefined (reading 'toUpperCase')Warum, und die Lösung
Ein geworfener String hat weder message noch name noch stack, Code, der einen Error erwartet, bricht also, und Sie verlieren die Stelle, an der es passiert ist. Werfen Sie ein Error-Objekt: throw new Error(`User ${id} not found`). Verwenden Sie einen eingebauten Typ wie TypeError oder RangeError, wenn er passt.
try {
const settings = JSON.parse('{"theme": "dark"}');
} catch (error) {
console.log("broken settings");
}
console.log(settings.theme);
Was Node.js ausgibt
ReferenceError: settings is not definedWarum, und die Lösung
const und let im try-Block gibt es nur in diesem Block. Verwenden Sie den Wert innerhalb von try oder deklarieren Sie ihn davor: let settings = {}; dann try { settings = JSON.parse(text); } catch { … }, damit er auch nach einem Fehler einen Wert hat.
let settings;
try {
settings = JSON.parse("{oops");
} catch (error) {
console.log("could not read the settings");
}
console.log(settings.theme);
Was Node.js ausgibt
TypeError: Cannot read properties of undefined (reading 'theme')Warum, und die Lösung
Der catch-Block gab eine Zeile aus, ließ settings aber undefined, sodass das Programm ein paar Zeilen später mit einem weniger hilfreichen Fehler scheitert. Ein catch muss das Programm in einem brauchbaren Zustand hinterlassen: Geben Sie settings dort einen Standardwert oder werfen Sie den Fehler weiter, wenn das Programm nicht fortfahren kann.
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.