Wenn der Browser kein Spielzeug, sondern ein Rechenzentrum ist
\n\nWir sind es gewohnt, dass JavaScript in der Browser-Sandbox lebt: Animationen, Klicks, Formulare. Aber was, wenn ich Ihnen sage, dass man mit reinem JS eine 500 MB große CSV-Datei verarbeiten, ein Diagramm mit 100.000 Punkten erstellen und den Tab nicht zum Absturz bringen kann? Das ist keine Science-Fiction, sondern der gekonnte Einsatz von Verarbeitung großer Datenmengen mit JavaScript.
\nIn diesem Artikel zeige ich Ihnen, wie Sie direkt im Browser mit großen Datenmengen arbeiten – ohne Backend, ohne Python, ohne Gigabyte auf den Server zu kopieren. Sie erfahren mehr über Streaming, Web Workers, Speicheroptimierung und Bibliotheken, die den Browser in einen Mini-Datenprozessor verwandeln. Los geht's!
\n\nWarum „naive“ Datenverarbeitung die Leistung tötet
\nStellen Sie sich vor: Sie laden eine 300 MB große CSV-Datei und schreiben:
\nconst data = await response.json(); // ❌ Fataler Fehler\nWas passiert? JS versucht, die gesamte Datei in den Arbeitsspeicher zu parsen. Wenn der Benutzer 4 GB RAM hat – stürzt der Browser ab. Selbst auf einem leistungsstarken PC beginnt der Garbage Collector zu „trödeln“ und die Oberfläche friert für eine Minute ein.
\nRegel Nr. 1: Laden Sie nicht alles auf einmal. Große Datenmengen in JavaScript erfordern eine Stream-Verarbeitung (Streaming) und die Aufteilung in Chunks.
\n\nDaten-Streaming: Datei stückweise lesen
\nDie Browser-API FileReader ermöglicht das Lesen einer Datei in Teilen. Noch praktischer ist jedoch ReadableStream. Beispiel: Verarbeitung einer großen JSON-Datei zeilenweise.
Beispiel: JSON-Streaming mit NDJSON
\nDas NDJSON-Format (jede Zeile ist ein separates JSON-Objekt) ist ideal für große Datenmengen. So lesen Sie es als Stream:
\nasync function* streamJSON(file) {\n const stream = file.stream();\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop(); // Rest in den Puffer\n for (const line of lines) {\n if (line.trim()) yield JSON.parse(line);\n }\n }\n}\n\n// Verwendung\nfor await (const obj of streamJSON(selectedFile)) {\n processRow(obj); // Ein Objekt nach dem anderen verarbeiten\n}\n\nDer Speicher wächst kaum – wir behalten nur eine Zeile im Speicher. Dieser Ansatz ist die Grundlage der Verarbeitung großer Datenmengen mit JavaScript in realen Projekten.
\n\nWeb Workers: Die Oberfläche nicht einfrieren
\nAuch Streaming wird im Hauptthread ausgeführt. Wenn die Berechnungen komplex sind, friert die UI ein. Lösung: Web Workers. Dies ist ein separater Thread, in dem Gigabyte ohne Verzögerungen verarbeitet werden können.
\n\nWorker zur CSV-Verarbeitung erstellen
\nWorker-Code (worker.js):
\nself.onmessage = async function(e) {\n const { file, chunkSize } = e.data;\n const reader = new FileReaderSync(); // Synchrones Lesen – für Worker erlaubt\n let offset = 0;\n const results = [];\n\n while (offset < file.size) {\n const blob = file.slice(offset, offset + chunkSize);\n const text = reader.readAsText(blob);\n const lines = text.split('\\n');\n for (const line of lines) {\n if (line.trim()) results.push(parseCSVLine(line));\n }\n offset += chunkSize;\n // Zwischenergebnis senden\n self.postMessage({ type: 'chunk', data: results.splice(0, results.length) });\n }\n self.postMessage({ type: 'done' });\n};\n\nfunction parseCSVLine(line) {\n const [name, age, city] = line.split(',');\n return { name, age: parseInt(age), city };\n}\n\nHauptthread:
\nconst worker = new Worker('worker.js');\nworker.postMessage({ file: csvFile, chunkSize: 1024 * 1024 }); // 1 MB Chunks\n\nworker.onmessage = (e) => {\n if (e.data.type === 'chunk') {\n updateUI(e.data.data); // Tabelle/Diagramm fließend aktualisieren\n }\n};\n\nJetzt bleibt die Oberfläche reaktionsfähig, selbst wenn wir 2 GB Daten verarbeiten. Dies ist eine Schlüsseltechnik für b