javascript - Cum să creezi stream-uri dintr-un șir de caractere în Node.Js?


Folosesc o bibliotecă, ya-csv, care așteaptă fie un fișier, fie un flux ca intrare, dar eu am un șir de caractere.

Cum pot să convertesc acel șir într-un flux în Node?

Răspuns #1

Așa cum @substack m-a corectat în #node, noul API de stream-uri din Node v10 face acest lucru mai ușor:

const Readable = require('stream').Readable;
const s = new Readable();
s._read = () => {}; // redundant? see update below
s.push('your text here');
s.push(null);

… după care îl poți transmite liber printr-un canal sau altfel către consumatorul tău dorit.

Nu este la fel de curat ca fraza scurtă din CV, dar evită totuși dependența suplimentară.

(Actualizare: în versiunile v0.10.26 până la v9.2.1 până acum, un apel la push direct din promptul REPL va da crash cu o excepție not implemented dacă nu ați setat _read. Nu va da crash într-o funcție sau într-un script. Dacă inconsistența vă face să fiți neliniștit, includeți noop.)

Răspunsul #2

Nu folosiți răspunsul de reluare al lui Jo Liss. Va funcționa în majoritatea cazurilor, dar în cazul meu mi-a făcut să pierd 4 sau 5 ore bune de identificare a erorilor. Nu este nevoie de module terțe pentru a face asta.

RĂSPUNS NOU:

var Readable = require('stream').Readable

var s = new Readable()
s.push('beep')    // the string you want
s.push(null)      // indicates end-of-file basically - the end of the stream

Acesta ar trebui să fie un flux Readable complet conform. Vezi aici pentru mai multe informații despre cum să folosești corect fluxurile.

RĂSPUNS VECHI: Folosește doar fluxul nativ PassThrough:

var stream = require("stream")
var a = new stream.PassThrough()
a.write("your string")
a.end()

a.pipe(process.stdout) // piping will work as normal
/*stream.on('data', function(x) {
   // using the 'data' event works too
   console.log('data '+x)
})*/
/*setTimeout(function() {
   // you can even pipe after the scheduler has had time to do other things
   a.pipe(process.stdout) 
},100)*/

a.on('end', function() {
    console.log('ended') // the end event will be called properly
})

Rețineți că evenimentul 'close' nu este emis (ceea ce nu este cerut de interfețele fluxurilor).

Răspunsul #3

Începând cu node 10.17, stream.Readable are o metodă from pentru a crea cu ușurință fluxuri din orice obiect iterabil (care include literaluri de array-uri):

const { Readable } = require("stream")

const readable = Readable.from(["input string"])

readable.on("data", (chunk) => {
  console.log(chunk) // will be called once with `"input string"`
})

Rețineți că cel puțin între 10.17 și 12.3, un șir de caractere este el însuși un iterable, așa că Readable.from("input string") va funcționa, dar va emite un eveniment pentru fiecare caracter. Readable.from(["input string"]) va emite un eveniment pentru fiecare element din array (în acest caz, un singur element).

De asemenea, rețineți că în nodurile ulterioare (probabil 12.3, deoarece documentația spune că funcția a fost schimbată atunci), nu mai este necesar să înveliți șirul într-un array.

https://nodejs.org/api/stream.html#stream_stream_readable_from_iterable_options

Răspunsul #4

Pur și simplu creează o nouă instanță a modulului stream și personalizeaz-o conform nevoilor tale:

var Stream = require('stream');
var stream = new Stream();

stream.pipe = function(dest) {
  dest.write('your string');
  return dest;
};

stream.pipe(process.stdout); // in this case the terminal, change to ya-csv

sau

var Stream = require('stream');
var stream = new Stream();

stream.on('data', function(data) {
  process.stdout.write(data); // change process.stdout to ya-csv
});

stream.emit('data', 'this is my string');

Răspunsul #5

Editare: Răspunsul lui Garth este probabil mai bun.

Textul meu vechi de răspuns este păstrat mai jos.

Pentru a converti un șir de caractere într-un flux, poți folosi un flux prin pauză:

through().pause().queue('your string').end()

Exemplu :

var through = require('through')

// Create a paused stream and buffer some data into it:
var stream = through().pause().queue('your string').end()

// Pass stream around:
callback(null, stream)

// Now that a consumer has attached, remember to resume the stream:
stream.resume()

Răspunsul #6

Există un modul pentru asta: https://www.npmjs.com/package/string-to-stream

var str = require('string-to-stream')
str('hi there').pipe(process.stdout) // => 'hi there'