Aufwärmen · Aufgabe 1 von 7
Zum Aufwärmen, aus Lektion I4.1: ein eingebauter Fehlertyp. Was gibt dieser Code aus?
const list = [];
try {
list.length = -1;
} catch (error) {
console.log(error.name);
}// I4.2 · ca. 34 Min. · Aufbau
Nach dieser Lektion geben Sie Ihrem Programm eigene Fehlertypen, entscheiden nach Typ statt nach Meldungstext und behalten den ursprünglichen Fehler, wenn Sie Kontext hinzufügen.
Danach können Sie
Aufwärmen · Aufgabe 1 von 7
const list = [];
try {
list.length = -1;
} catch (error) {
console.log(error.name);
}Vorhersagen · Aufgabe 2 von 7
class NotFoundError extends Error {}
const error = new NotFoundError("No user with id 2");
console.log(error.name, error instanceof NotFoundError);Üben · Aufgabe 3 von 7
super(message, ____);Üben · Aufgabe 4 von 7
class AppError extends Error {}
class DbError extends AppError {}
const error = new DbError("Connection lost");
console.log(error instanceof AppError, error instanceof TypeError);Üben · Aufgabe 5 von 7
const low = new Error("ECONNREFUSED");
const high = new Error("Could not load users", {cause: low});
console.log(high.message + " / " + high.cause.message);Denksport · Aufgabe 6 von 7
class ValidationError extends Error {
constructor(field, message) {
super(message);
this.name = "ValidationError";
this.field = field;
}
}
console.log(JSON.stringify(new ValidationError("email", "Email is missing")));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
NotFoundError trägt die id, die nicht gefunden wurde, und die Schleife behandelt nur diesen Typ, jeder andere Fehler würde das Programm also weiterhin stoppen. ValidationError zeigt das vollständige Muster: options an super weitergereicht, ein name und ein Feld. parseSettings umhüllt den SyntaxError von JSON.parse mit einem Fehler, der sagt, was das Programm gerade tat.
main.js
class ValidationError extends Error {
constructor(field, message, options) {
super(message, options); // first: sets message, and cause if given
this.name = "ValidationError";
this.field = field;
}
}
class NotFoundError extends Error {
constructor(id) {
super(`No user with id ${id}`);
this.name = "NotFoundError";
this.id = id;
}
}
const users = new Map([[1, {name: "Ada"}]]);
function findUser(id) {
const user = users.get(id);
if (!user) throw new NotFoundError(id);
return user;
}
function parseSettings(text) {
try {
return JSON.parse(text);
} catch (error) {
throw new Error("Could not read the settings", {cause: error});
}
}
for (const id of [1, 2]) {
try {
console.log(findUser(id).name);
} catch (error) {
if (error instanceof NotFoundError) console.log("404:", error.message);
else throw error;
}
}
const invalid = new ValidationError("email", "Email is missing");
console.log(String(invalid), invalid.field, invalid instanceof Error);
try {
parseSettings("{oops");
} catch (error) {
console.log(error.message, "<-", error.cause.name);
}
Ausführen mit
node main.jsAusgabe
Ada
404: No user with id 2
ValidationError: Email is missing email true
Could not read the settings <- SyntaxErrorTab 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
HttpError soll den HTTP-Status einer fehlgeschlagenen Anfrage tragen: new HttpError(503, "Service unavailable") hat den name HttpError, die Meldung und ein Feld status. isRetryable(error) ist nur für einen HttpError mit einem Status ab 500 true. Die Klasse im Starter setzt weder name noch status.
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: Was zeigt String(error) als name, und was ist error.status?
Setzen Sie nach super(message) this.name und this.status.
Reichen Sie auch options weiter, damit ein HttpError eine Ursache tragen kann.
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
export class HttpError extends Error {
constructor(status, message, options) {
super(message, options);
this.name = "HttpError";
this.status = status;
}
}
export function isRetryable(error) {
return error instanceof HttpError && error.status >= 500;
}
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 class HttpError extends Error {
constructor(status, message) {
super(message);
}
}
export function isRetryable(error) {
return error instanceof HttpError && error.status >= 500;
}
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {HttpError, isRetryable} from './main.js';
test('ein HttpError hat name, Meldung und Status', () => {
const error = new HttpError(503, 'Service unavailable');
assert.equal(String(error), 'HttpError: Service unavailable', `String(error) ist ${String(error)}`);
assert.equal(error.status, 503, `error.status ist ${error.status}`);
assert.ok(error instanceof Error, 'ein HttpError sollte ein Error sein');
});
test('eine 503 lässt sich wiederholen, eine 404 nicht', () => {
assert.equal(isRetryable(new HttpError(503, 'Service unavailable')), true, 'eine 503 sollte wiederholbar sein');
assert.equal(isRetryable(new HttpError(404, 'Not found')), false, 'eine 404 sollte nicht wiederholbar sein');
});
test('andere Fehler werden nie wiederholt', () => {
assert.equal(isRetryable(new TypeError('x is not a function')), false, 'ein TypeError sollte nicht wiederholbar 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 herunterladenÜbung 2 von 2
loadConfig(text) parst eine als JSON geschriebene Konfiguration. Bei kaputtem JSON wirft es einen ConfigError mit der Meldung Config is not valid JSON und dem SyntaxError als Ursache. loadConfig übergibt {cause: error} bereits, aber die Ursache geht unterwegs verloren. Finden Sie die Stelle und beheben Sie es.
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.
Wer liest das options-Objekt mit der Ursache darin?
Der constructor von ConfigError reicht das zweite Argument nie an Error weiter.
constructor(message, options) { super(message, options); … }
Ein möglicher Lösungsweg. Ihrer kann anders aussehen und trotzdem alle Prüfungen bestehen.
export class ConfigError extends Error {
constructor(message, options) {
super(message, options);
this.name = "ConfigError";
}
}
export function loadConfig(text) {
try {
return JSON.parse(text);
} catch (error) {
throw new ConfigError("Config is not valid JSON", {cause: 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 class ConfigError extends Error {
constructor(message) {
super(message);
this.name = "ConfigError";
}
}
export function loadConfig(text) {
try {
return JSON.parse(text);
} catch (error) {
throw new ConfigError("Config is not valid JSON", {cause: error});
}
}
main.test.js
import {test} from 'node:test';
import assert from 'node:assert/strict';
import {ConfigError, loadConfig} from './main.js';
test('gültiges JSON kommt als Objekt zurück', () => {
assert.deepEqual(loadConfig('{"port": 8080}'), {port: 8080}, 'loadConfig sollte gültiges JSON parsen');
});
test('kaputtes JSON wirft einen ConfigError', () => {
assert.throws(() => loadConfig('{port'), ConfigError, 'loadConfig sollte einen ConfigError werfen');
});
test('der ConfigError behält den SyntaxError als Ursache', () => {
try {
loadConfig('{port');
assert.fail('loadConfig hat nicht geworfen');
} catch (error) {
assert.ok(error.cause instanceof SyntaxError, `error.cause ist ${error.cause}`);
}
});
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 herunterladenclass ValidationError extends Error {
constructor(field, message) {
this.field = field;
super(message);
}
}
new ValidationError("email", "Email is missing");
Was Node.js ausgibt
ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructorWarum, und die Lösung
In einer Klasse, die eine andere erweitert, wird das Objekt vom constructor der Elternklasse erzeugt, this existiert also nicht, bevor super() gelaufen ist. Rufen Sie super(message, options) als erste Zeile des constructors auf und setzen Sie dann name und die anderen Felder.
class LoadError extends Error {
constructor(message) {
super(message);
this.name = "LoadError";
}
}
try {
throw new LoadError("Could not load", {cause: new Error("timeout")});
} catch (error) {
console.log(error.cause.message);
}
Was Node.js ausgibt
TypeError: Cannot read properties of undefined (reading 'message')Warum, und die Lösung
Error setzt cause nur aus dem options-Objekt, das es bekommt, und dieser constructor reicht es nie weiter, error.cause ist also undefined. Nehmen Sie options entgegen und geben Sie sie an super weiter: constructor(message, options) { super(message, options); … }.
class NotFoundError extends Error {
constructor(id) {
super(`No user with id ${id}`);
this.name = "NotFoundError";
}
}
throw NotFoundError(2);
Was Node.js ausgibt
TypeError: Class constructor NotFoundError cannot be invoked without 'new'Warum, und die Lösung
Das eingebaute Error() funktioniert auch ohne new, eine Klasse aber nie. Schreiben Sie throw new NotFoundError(2).
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.