Risposte:
Dal nodo 10.17, stream.Readable ha un from
metodo per creare facilmente flussi da qualsiasi iterabile (che include valori letterali di array):
const { Readable } = require("stream")
const readable = Readable.from(["input string"])
readable.on("data", (chunk) => {
console.log(chunk) // will be called once with `"input string"`
})
Nota che almeno tra 10.17 e 12.3, una stringa è essa stessa un iterabile, quindi Readable.from("input string")
funzionerà, ma emetterà un evento per carattere. Readable.from(["input string"])
emetterà un evento per elemento nell'array (in questo caso, un elemento).
Si noti inoltre che nei nodi successivi (probabilmente 12.3, poiché la documentazione indica che la funzione è stata modificata in quel momento), non è più necessario avvolgere la stringa in un array.
https://nodejs.org/api/stream.html#stream_stream_readable_from_iterable_options
Poiché @substack mi ha corretto in #node , la nuova API stream in Node v10 rende tutto più semplice:
const Readable = require('stream').Readable;
const s = new Readable();
s._read = () => {}; // redundant? see update below
s.push('your text here');
s.push(null);
... dopo di che puoi liberamente pipe o in altro modo passarlo al consumatore previsto.
Non è pulito come il resumer one-liner, ma evita la dipendenza aggiuntiva.
( Aggiornamento: dalla v0.10.26 alla v9.2.1 finora, una chiamata a push
direttamente dal prompt REPL si arresta in modo anomalo con not implemented
un'eccezione se non è stata impostata _read
. Non si arresta in modo anomalo all'interno di una funzione o di uno script. Se l'incoerenza ti rende nervoso, includi il noop
.)
_read
metodo per recuperare i dati dalla risorsa sottostante."
null
nel buffer del flusso?
null
dice allo stream che ha finito di leggere tutti i dati e di chiudere lo stream
readable.push()
metodo è destinato a essere chiamato solo dagli Implementatori leggibili e solo dall'interno del readable._read()
metodo."
Non usare la risposta del resumer di Jo Liss. Funzionerà nella maggior parte dei casi, ma nel mio caso mi ha perso una buona ricerca di bug di 4 o 5 ore. Non è necessario che moduli di terze parti facciano questo.
NUOVA RISPOSTA :
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
Questo dovrebbe essere un flusso leggibile pienamente conforme. Vedi qui per maggiori informazioni su come usare gli stream correttamente.
RISPOSTA VECCHIA : basta usare il flusso PassThrough nativo:
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
})
Si noti che l'evento 'close' non viene emesso (che non è richiesto dalle interfacce dello stream).
Basta creare una nuova istanza del stream
modulo e personalizzarla in base alle proprie esigenze:
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
o
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');
pipe()
dovrebbe restituire il flusso di destinazione, almeno.
Modifica: la risposta di Garth è probabilmente migliore.
Il mio vecchio testo di risposta è conservato di seguito.
Per convertire una stringa in un ruscello, è possibile utilizzare un pausa attraverso il flusso:
through().pause().queue('your string').end()
Esempio:
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()
resumer
funzionava abbastanza bene. Grazie!
C'è un modulo per questo: https://www.npmjs.com/package/string-to-stream
var str = require('string-to-stream')
str('hi there').pipe(process.stdout) // => 'hi there'
Un'altra soluzione sta passando la funzione di lettura al costruttore di Readable (vedi opzioni leggibili del flusso di documenti )
var s = new Readable({read(size) {
this.push("your string here")
this.push(null)
}});
dopo l'uso puoi usare s.pipe per esempio
Mi sono stancato di doverlo imparare di nuovo ogni sei mesi, quindi ho appena pubblicato un modulo npm per sottrarre i dettagli dell'implementazione:
https://www.npmjs.com/package/streamify-string
Questo è il nucleo del modulo:
const Readable = require('stream').Readable;
const util = require('util');
function Streamify(str, options) {
if (! (this instanceof Streamify)) {
return new Streamify(str, options);
}
Readable.call(this, options);
this.str = str;
}
util.inherits(Streamify, Readable);
Streamify.prototype._read = function (size) {
var chunk = this.str.slice(0, size);
if (chunk) {
this.str = this.str.slice(size);
this.push(chunk);
}
else {
this.push(null);
}
};
module.exports = Streamify;
str
è quello string
che deve essere passato al costruttore al momento dell'invocazione e verrà emesso dal flusso come dati. options
sono le opzioni tipiche che possono essere passate a un flusso, secondo la documentazione .
Secondo Travis CI, dovrebbe essere compatibile con la maggior parte delle versioni del nodo.
Ecco una soluzione ordinata in TypeScript:
import { Readable } from 'stream'
class ReadableString extends Readable {
private sent = false
constructor(
private str: string
) {
super();
}
_read() {
if (!this.sent) {
this.push(Buffer.from(this.str));
this.sent = true
}
else {
this.push(null)
}
}
}
const stringStream = new ReadableString('string to be streamed...')
JavaScript è di tipo anatra, quindi se copi semplicemente l'API di un flusso leggibile , funzionerà perfettamente. In effetti, probabilmente non puoi implementare la maggior parte di questi metodi o semplicemente lasciarli come stub; tutto ciò che devi implementare è ciò che utilizza la libreria. Puoi anche usare la EventEmitter
classe pre-costruita di Node per gestire gli eventi, quindi non devi implementare addListener
te stesso.
Ecco come è possibile implementarlo in CoffeeScript:
class StringStream extends require('events').EventEmitter
constructor: (@string) -> super()
readable: true
writable: false
setEncoding: -> throw 'not implemented'
pause: -> # nothing to do
resume: -> # nothing to do
destroy: -> # nothing to do
pipe: -> throw 'not implemented'
send: ->
@emit 'data', @string
@emit 'end'
Quindi potresti usarlo in questo modo:
stream = new StringStream someString
doSomethingWith stream
stream.send()
TypeError: string is not a function at String.CALL_NON_FUNCTION (native)
quando lo uso in questo modonew StringStream(str).send()
stream.Readable
come suggerito da @Garth Kidd.
stream.Readable
non esisteva quando ho scritto questa risposta.