trasformare
I flussi di trasformazione sono sia leggibili che scrivibili, e quindi sono flussi "medi" davvero buoni. Per questo motivo, a volte vengono definiti through
flussi. Sono simili a un flusso duplex in questo modo, tranne per il fatto che forniscono un'interfaccia piacevole per manipolare i dati anziché semplicemente inviarli. Lo scopo di un flusso di trasformazione è manipolare i dati mentre vengono inviati attraverso il flusso. Potresti voler fare alcune chiamate asincrone, ad esempio, o derivare un paio di campi, rimappare alcune cose, ecc.
Per come creare un flusso di trasformazione, vedere qui e qui . Tutto quello che devi fare è:
- include il modulo stream
- istanziare (o ereditare da) la classe Transform
- implementare un
_transform
metodo che richiede a (chunk, encoding, callback)
.
Il pezzo è i tuoi dati. La maggior parte delle volte non dovrai preoccuparti della codifica se lavori objectMode = true
. Il callback viene chiamato al termine dell'elaborazione del blocco. Questo blocco viene quindi trasferito al flusso successivo.
Se vuoi un bel modulo di supporto che ti permetta di fare lo streaming davvero molto facilmente, ti suggerisco through2 .
Per la gestione degli errori, continua a leggere.
tubo
In una catena di condotte, la gestione degli errori non è affatto banale. Secondo questo thread .pipe () non è costruito per inoltrare errori. Quindi qualcosa come ...
var a = createStream();
a.pipe(b).pipe(c).on('error', function(e){handleError(e)});
... ascolterebbe solo errori sullo stream c
. Se si generasse un evento di errore a
, questo non verrebbe trasmesso e, di fatto, verrebbe lanciato. Per farlo correttamente:
var a = createStream();
a.on('error', function(e){handleError(e)})
.pipe(b)
.on('error', function(e){handleError(e)})
.pipe(c)
.on('error', function(e){handleError(e)});
Ora, sebbene il secondo modo sia più dettagliato, puoi almeno mantenere il contesto in cui si verificano i tuoi errori. Questa è generalmente una buona cosa.
Una libreria che trovo utile, tuttavia, se hai un caso in cui vuoi solo catturare gli errori a destinazione e non ti interessa tanto dove è successo è il flusso di eventi .
fine
Quando viene generato un evento di errore, l'evento finale non verrà generato (esplicitamente). L'emissione di un evento di errore interromperà il flusso.
domini
Nella mia esperienza, i domini funzionano davvero bene per la maggior parte del tempo. Se si verifica un evento di errore non gestito (ovvero l'emissione di un errore su uno stream senza un listener), il server può arrestarsi in modo anomalo. Ora, come sottolineato nell'articolo precedente, puoi avvolgere lo stream in un dominio che dovrebbe rilevare correttamente tutti gli errori.
var d = domain.create();
d.on('error', handleAllErrors);
d.run(function() {
fs.createReadStream(tarball)
.pipe(gzip.Gunzip())
.pipe(tar.Extract({ path: targetPath }))
.on('close', cb);
});
Il bello dei domini è che manterranno le tracce dello stack. Anche il flusso di eventi fa un buon lavoro anche in questo.
Per ulteriori letture, consulta il manuale del flusso . Abbastanza approfondito, ma super utile e offre ottimi collegamenti a molti moduli utili.
Promise
i framework rendono tutto molto più semplice