Abschnitt 3 · Lektion 6
Synthese: die Notizverwaltung
Fünf Lektionen, fünf Bausteine: lesen, schreiben, Ordner, JSON, Fehler. Diese Lektion setzt sie zusammen, und zwar zu genau dem Ablauf, den du in kleinen Werkzeugen immer wieder brauchst.
Der Ablauf in vier Schritten
Ordner sicherstellen. mkdir mit recursive: true, und zwar bedingungslos vor dem Schreiben.
import { mkdir, readdir } from "node:fs/promises";
await mkdir("daten/2026", { recursive: true });
await mkdir("daten/2026", { recursive: true });
console.log("Zweimal aufgerufen, kein Fehler.");
console.log("Vorhanden:", await readdir("daten")); Das ist der Grund, warum man diese Option praktisch immer setzt: Der Aufruf beschwert sich nicht,
wenn schon alles da ist. Damit brauchst du keine Prüfung davor und keinen try darum.
Laden oder mit einem Standard anfangen. Beim ersten Start gibt es die Datei nicht, und das ist kein Fehler.
import { readFile } from "node:fs/promises";
async function laden(pfad) {
try {
return JSON.parse(await readFile(pfad, "utf8"));
} catch (fehler) {
if (fehler.code === "ENOENT") return [];
throw fehler;
}
}
const notizen = await laden("daten/notizen.json");
console.log("Geladen:", notizen.length, "Notizen");
console.log("Fängt also frisch an:", notizen.length === 0); Beachte, was hier passiert und was nicht: ENOENT wird abgefangen und beantwortet, jeder andere
Fehler fliegt weiter. Eine kaputte JSON-Datei oder fehlende Rechte sollen dein Programm anhalten,
nicht in eine leere Liste verwandeln. Sonst überschreibst du im nächsten Schritt eine Datei voller
Daten mit einem leeren Array, und niemand merkt es.
Ändern. Ab hier ist es ganz normales JavaScript: push, find, filter. Die Daten liegen als
Objekt im Speicher und wissen nichts mehr von einer Datei.
Ganz zurückschreiben. JSON.stringify und writeFile, in einem Zug.
Warum das Muster funktioniert
Die Stärke dieses Ablaufs ist, dass es zwischen Laden und Schreiben keinen Zwischenzustand gibt. Die Datei ist entweder der alte Stand oder der neue. Du musst dir nie merken, welche Änderungen schon gespeichert sind und welche nicht.
Für ein Kommandozeilenwerkzeug ist das genau richtig. Es läuft, macht eine Sache, schreibt einmal und ist fertig.
Und wo es aufhört
Jetzt der ehrliche Teil.
import { mkdir, readFile, writeFile } from "node:fs/promises";
const PFAD = "daten/liste.json";
async function hinzufuegen(text) {
let liste = [];
try {
liste = JSON.parse(await readFile(PFAD, "utf8"));
} catch {
liste = [];
}
liste.push(text);
await writeFile(PFAD, JSON.stringify(liste));
}
await mkdir("daten", { recursive: true });
await writeFile(PFAD, "[]");
await hinzufuegen("A");
await hinzufuegen("B");
console.log("Nacheinander gespeichert:", JSON.parse(await readFile(PFAD, "utf8")).length);
await writeFile(PFAD, "[]");
await Promise.all([hinzufuegen("A"), hinzufuegen("B")]);
console.log("Gleichzeitig gespeichert:", JSON.parse(await readFile(PFAD, "utf8")).length); Zweimal derselbe Vorgang, einmal nacheinander und einmal gleichzeitig. Nacheinander landen beide Einträge in der Datei. Gleichzeitig landet nur einer.
Der Grund ist offensichtlich, sobald man ihn sieht: Beide Abläufe lesen dieselbe leere Liste, beide hängen ihren Eintrag an ihre eigene Kopie an, beide schreiben die ganze Datei. Der zweite Schreiber überschreibt den ersten samt seinem Eintrag. Verloren geht nichts mit einem Knall, sondern still.
Bei einem Kommandozeilenwerkzeug passiert das nie, weil nur ein Ablauf läuft. Bei einem Webserver mit mehreren gleichzeitigen Anfragen passiert es dauernd, und je mehr Betrieb du hast, desto öfter.
Das ist keine Schwäche von JSON und keine von Node, sondern die Eigenschaft von „erst ganz lesen, dann ganz schreiben”. Die Lösung heißt Datenbank: Sie kann einen einzelnen Eintrag ändern, ohne die anderen anzufassen, und sie regelt, wer wann darf. Genau da fängt Abschnitt 12 an, und dann wirst du diesen Wettlauf wiedererkennen.
Bis dahin gilt: Für alles, was du in diesem Kurs baust, reicht die Datei. Aber du weißt jetzt, wo die Grenze liegt, und das ist mehr wert als die Datei selbst.
Zum Mitnehmen
Erst ganz lesen, dann ganz schreiben ist bei kleinen Datenmengen richtig. Ab zwei gleichzeitigen Schreibern ist es kaputt.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.
Was in dieser Lektion steckt
-
Artikel mit 3 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe, dein Code läuft auf einem Server
Öffnet sich mit dem Basis Konto.