Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 2 di 2
  • livello principiante
Indice lezioni

Parsing progressivo di un CSV molto grande

Scopriamo come gestire file di grandi dimensioni in JavaScript quando si passa dal semplice split per righe a un formato reale come CSV
Scopriamo come gestire file di grandi dimensioni in JavaScript quando si passa dal semplice split per righe a un formato reale come CSV
Link copiato negli appunti

Quando si passa dal semplice split per righe a un formato reale come CSV, la logica si arricchisce.

Esempio di parser CSV

Ora, supponiamo di avere un CSV semplice, senza campi multilinea e senza virgolette annidate. Anche in questa versione semplificata è già chiaro il vantaggio del parsing progressivo.

function parseCsvLine(linea) {
  return linea.split(",");
}
async function leggiCsvGigante(file, onRecord) {
  let intestazioni = null;
  await processaRighe(file, async (riga) => {
    if (!riga.trim()) return;
    const valori = parseCsvLine(riga);
    if (!intestazioni) {
      intestazioni = valori;
      return;
    }
    const record = Object.fromEntries(
      intestazioni.map((chiave, indice) => [chiave, valori[indice] ?? ""])
    );
    await onRecord(record);
  });
}

Qui il punto non è tanto la completezza del parser CSV, quanto la struttura del lavoro. Ogni riga viene letta, trasformata e consegnata a una funzione applicativa onRecord. Questa funzione potrebbe aggiornare una barra di progresso, filtrare risultati, salvare dati in IndexedDB, inviare batch a un worker o costruire statistiche senza mai dover attendere la fine dell'intero file.

Il beneficio lato esperienza utente è notevole. Invece di un'interfaccia bloccata per lunghi secondi, si può mostrare attività immediata. Il parsing comincia subito, e l'utente percepisce che il sistema sta lavorando in modo continuo.

Oltre i CSV, quando serve davvero una pipeline di trasformazioni

Uno degli aspetti più eleganti delle Web Streams API è la possibilità di comporre trasformazioni distinte. In un parsing realistico di file molto grandi, conviene quasi sempre separare le responsabilità. Una trasformazione può occuparsi della decodifica del testo. Un'altra della suddivisione in righe. Un'altra ancora della normalizzazione. Un'ultima del parsing vero e proprio in oggetti dominio.

Questa divisione rende il codice più chiaro perché ogni fase risolve un problema preciso. Allo stesso tempo, la pipeline resta efficiente perché i dati scorrono senza bisogno di materializzare risultati intermedi enormi. Il metodo pipeThrough() esiste proprio per costruire queste catene in modo naturale. MDN lo descrive infatti come il modo concatenabile per far passare uno stream corrente attraverso una trasformazione o una coppia writable/readable.

Un esempio un po' più strutturato può essere questo:

function creaParserJsonLines() {
  return new TransformStream({
    transform(riga, controller) {
      const testo = riga.trim();
      if (!testo) return;
      controller.enqueue(JSON.parse(testo));
    }
  });
}
async function leggiJsonLines(file, onOggetto) {
  const stream = file
    .stream()
    .pipeThrough(new TextDecoderStream())
    .pipeThrough(creaSplitPerRighe())
    .pipeThrough(creaParserJsonLines());
  for await (const oggetto of stream) {
    await onOggetto(oggetto);
  }
}

In tale scenario ogni riga contiene un oggetto JSON autonomo. È un formato molto diffuso nei sistemi di logging e negli export massivi proprio perché si presta bene allo streaming. Il codice resta leggibile e il consumo di memoria resta sotto controllo.

La backpressure non è un dettaglio, è una protezione

Quando si parla di stream, spesso ci si concentra sulla comodità del leggere "a pezzi". Ma il valore delle Streams API non si esaurisce lì. Lo standard insiste anche sul concetto di backpressure, cioè sul meccanismo con cui una pipeline evita che i produttori di dati travolgano i consumatori. In un sistema reale questo significa poter rallentare la produzione quando la fase successiva è più lenta, evitando code interne ingestibili o crescita incontrollata della memoria.

Questo aspetto diventa particolarmente importante quando il parsing non è banale. Se ogni record richiede validazione, arricchimento o persistenza, il consumo può diventare più lento della lettura. Una pipeline ben costruita aiuta a far sì che il sistema resti stabile, invece di accumulare dati in modo indiscriminato.

Browser, worker e anche Node.js

Anche se il nome può far pensare a un contesto esclusivamente browser, le Web Streams API non sono più un tema confinato al frontend. Node.js ha introdotto l'esposizione globale della Web Streams API già con Node 18, inizialmente come funzionalità sperimentale, includendo tra gli oggetti disponibili anche ReadableStream, TransformStream, TextEncoderStream e TextDecoderStream. Questo rende molto più facile condividere modelli mentali e, in certi casi, anche codice tra ambienti client e server.

Questo è interessante soprattutto per chi costruisce strumenti di importazione dati, processi ETL o interfacce amministrative che hanno una parte nel browser e una parte nel backend. L'idea di pipeline a stream non cambia: cambia solo il contesto in cui la si esegue.

Perché questo approccio cambia davvero il parsing di file giganti

Sfruttare le Web Streams API per il parsing di file giganti significa cambiare prospettiva. Non si tratta semplicemente di usare un'API diversa. Si tratta di abbandonare l'idea che il file sia un blocco da caricare tutto insieme e adottare invece un modello progressivo, incrementale e molto più vicino alla natura reale dei dati.

Il guadagno non è solo nella memoria risparmiata. È nella possibilità di iniziare il lavoro subito, di costruire pipeline chiare, di trattare il parsing come una sequenza di trasformazioni, di mantenere l'interfaccia più reattiva e di gestire in modo più robusto carichi che, con un approccio tradizionale, diventerebbero rapidamente ingestibili.

Per file piccoli forse la differenza si nota poco. Per file davvero grandi, invece, è il confine tra un'applicazione che resiste e una che si spezza. Ed è proprio in quel confine che le Web Streams API mostrano tutto il loro valore.

Se vuoi aggiornamenti su Parsing progressivo di un CSV molto grande inserisci la tua email nel box qui sotto:

Compilando il presente form acconsento a ricevere le informazioni relative ai servizi di cui alla presente pagina ai sensi dell'informativa sulla privacy.

Ti consigliamo anche