javascript - passthrough - ¿Cómo crear secuencias de cadena en Node.Js?
stream javascript (9)
Estoy usando una biblioteca, ya-csv , que espera un archivo o una secuencia como entrada, pero tengo una cadena.
¿Cómo convierto esa cadena en una secuencia en Node?
Como @substack me corrigió en #node , la nueva API de transmisiones en el Nodo v10 lo hace más fácil:
var Readable = require(''stream'').Readable;
var s = new Readable();
s._read = function noop() {}; // redundant? see update below
s.push(''your text here'');
s.push(null);
... después de lo cual puede pipe libremente o pasarlo a su consumidor previsto.
No es tan limpio como el resumer una línea, pero evita la dependencia adicional.
( Actualización: en v0.10.26 hasta v9.2.1 hasta el momento, una llamada para push
directamente desde el indicador REPL se bloqueará con una excepción not implemented
si no configuró _read
. No se bloqueará dentro de una función o un script. Si la inconsistencia te pone nervioso, incluye el noop
.)
Hay un módulo para eso: https://gist.github.com/kawanet/8aea35dc4a578f09757d
/**
* @see https://www.npmjs.com/package/string-to-stream
*/
var str = require(''string-to-stream'')
str(''hi there'').pipe(process.stdout) // => ''hi there''
JavaScript está escrito en pato, por lo que si solo copia la API de una secuencia legible , funcionará perfectamente. De hecho, probablemente no pueda implementar la mayoría de esos métodos o simplemente dejarlos como talones; todo lo que necesitará implementar es lo que usa la biblioteca. También puede usar la clase EventEmitter
para tratar los eventos, de modo que no tenga que implementar addListener
y usted mismo.
Así es cómo puede implementarlo en 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''
Entonces podrías usarlo así:
stream = new StringStream someString
doSomethingWith stream
stream.send()
Me cansé de tener que volver a aprender esto cada seis meses, así que acabo de publicar un módulo npm para abstraer los detalles de implementación:
https://www.npmjs.com/package/streamify-string
Este es el núcleo del módulo:
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
es la string
que se debe pasar al constructor al invocarse, y la corriente la generará como datos. options
son las opciones típicas que se pueden pasar a una secuencia, según la documentación .
Según Travis CI, debería ser compatible con la mayoría de las versiones de nodo.
No use la respuesta de reanudación de Jo Liss. Funcionará en la mayoría de los casos, pero en mi caso me ha dejado una buena búsqueda de errores de 4 o 5 horas. No hay necesidad de módulos de terceros para hacer esto.
NUEVA RESPUESTA :
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
Esta debería ser una transmisión legible completamente compatible. Consulte aquí para obtener más información sobre cómo usar las transmisiones de manera adecuada.
ANTIGUA RESPUESTA : Solo usa la transmisión nativa 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
})
Tenga en cuenta que el evento ''cerrar'' no se emite (lo cual no es requerido por las interfaces de flujo).
Otra solución es pasar la función de lectura al constructor de lectura legible (ver opciones de lectura de flujo de doc)
var s = new Readable({read(size) {
this.push("your string here")
this.push(null)
}});
usted puede después de usar en el tubo para ejemplo
Simplemente cree una nueva instancia del módulo de stream
y personalícelo según sus necesidades:
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'');
en coffee-script:
class StringStream extends Readable
constructor: (@str) ->
super()
_read: (size) ->
@push @str
@push null
usarlo:
new StringStream(''text here'').pipe(stream1).pipe(stream2)
Editar: la respuesta de Garth es probablemente mejor.
Mi antiguo texto de respuesta se conserva a continuación.
Para convertir una cadena en una secuencia, puede usar una secuencia en pausa:
through().pause().queue(''your string'').end()
Ejemplo:
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()