logo hsb.horse
← Zur Snippets-Übersicht

Snippets

Text mit TransformStream aufteilen

Ein TypeScript-Beispiel zur Verwendung von ReadableStream und TransformStream, um langen Text in Chunks einer bestimmten Größe aufzuteilen.

Veröffentlicht: Aktualisiert:

Ich wollte den Umgang mit der Stream API besser beherrschen und habe daher mit String-Manipulation als Beispiel experimentiert. Dies implementiert einen TransformStream, der langen Text in Arrays einer bestimmten Größe aufteilt.

Implementierung

type Ctrl = TransformStreamDefaultController<string[]>;
class TextArrayTransformStream extends TransformStream<string, string[]> {
#chunk: string[] = [];
#chunkSize: number;
#splitReg: RegExp;
constructor(chunkSize: number, maxTextLength: number) {
super({
transform: (chunk, controller) => this.#handle(chunk, controller),
flush: (controller) => this.#flush(controller),
});
this.#chunkSize = chunkSize;
this.#splitReg = new RegExp(`.{1,${maxTextLength}}`, "g");
}
#handle(chunk: string, controller: Ctrl): void {
for (const str of chunk.match(this.#splitReg) || []) {
if (this.#chunk.length >= this.#chunkSize) {
controller.enqueue(this.#chunk);
this.#chunk = [];
} else {
this.#chunk.push(str);
}
}
}
#flush(controller: Ctrl): void {
if (this.#chunk.length > 0) {
controller.enqueue(this.#chunk);
}
}
}

Hilfsfunktion

function toReadableStream(text: string): ReadableStream<string> {
return new ReadableStream({
start(controller) {
controller.enqueue(text);
controller.close();
}
});
}

Verwendungsbeispiel

async function main() {
const text = "Langer Text...";
const arrayLength = 5; // In Gruppen zu je 5 Elementen
const textLength = 10; // Jedes Element hat 10 Zeichen
const stream = toReadableStream(text)
.pipeThrough(new TextArrayTransformStream(arrayLength, textLength));
const reader = stream.getReader();
while (true) {
const { done, value } = await reader.read();
if (done) break;
console.log(value); // string[] wird sequentiell ausgegeben
}
}

Anwendungsfälle

Dieses Muster ist in folgenden Szenarien effektiv:

  • Beim Batch-Verarbeiten von LLM-API-Antworten
  • Beim paginierten Anzeigen großer Textmengen
  • Vorverarbeitung vor dem Senden an APIs mit Zeichenbegrenzung

Beachten Sie, dass AsyncIterator nicht implementiert ist, daher kann die for await…of-Syntax nicht verwendet werden.

Praxishinweis

Dieses Snippet passt gut, wenn dieselbe Operation oder Prüfung im Umfeld von TypeScript, JavaScript, Stream nicht immer wieder neu geschrieben werden soll. Als kleine Hilfsfunktion bleibt aufrufender Code leichter lesbar.

Wenn jedoch Verzweigungen und Voraussetzungen zunehmen, sollte nicht alles in ein einziges Snippet gepackt werden. Getrennte Schritte und klar abgegrenzte Helfer bleiben auf Dauer wartbarer.