logo hsb.horse
← Retour à l’index des snippets

Snippets

Découpage de texte avec TransformStream

Un exemple d'implémentation TypeScript utilisant ReadableStream et TransformStream pour diviser un long texte en morceaux de taille spécifiée.

Publié: Mis à jour:

Je voulais mieux maîtriser l’API Stream, alors j’ai expérimenté avec la manipulation de chaînes comme exemple. Cela implémente un TransformStream qui divise un long texte en tableaux d’une taille spécifique.

Implémentation

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);
}
}
}

Fonction auxiliaire

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

Exemple d’utilisation

async function main() {
const text = "Long texte...";
const arrayLength = 5; // Grouper par 5 éléments
const textLength = 10; // Chaque élément fait 10 caractères
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[] sort séquentiellement
}
}

Cas d’utilisation

Ce pattern est efficace dans les scénarios suivants :

  • Lors du traitement par lots des réponses d’API LLM
  • Lors de l’affichage paginé de grands textes
  • Prétraitement avant envoi à des API avec limitation de caractères

Notez qu’AsyncIterator n’est pas implémenté, donc la syntaxe for await…of ne peut pas être utilisée.