14

I'm trying to stream a string to another stream:

streamer = new stream.Transform objectMode: true
stringer = (string) ->
    streamer._transform = (chunk, encoding, done) ->
        @push string.split('').shift()
        done()

    return streamer

streamer.on 'readable', ->
    console.log 'readable'

stringer('hello').pipe process.stdout

But nothing logs in the console. What am I doing wrong?

Imaky
  • 1,227
  • 1
  • 16
  • 36
dopatraman
  • 13,416
  • 29
  • 90
  • 154
  • duplicate? http://stackoverflow.com/questions/12755997/how-to-create-streams-from-string-in-node-js – markasoftware Feb 22 '16 at 04:07
  • The source code of [`string-stream`](https://github.com/mikanda/string-stream/blob/master/index.js) could be as reference.. – zangw Feb 22 '16 at 04:30
  • Note: The code in this question is CoffeeScript, not JavaScript. – mklement0 Feb 22 '16 at 04:55
  • @Markasoftware when I run the code in that example i get this error: `_stream_readable.js:480 dest.on('unpipe', onunpipe); ^ TypeError: Cannot read property 'on' of undefined` – dopatraman Feb 23 '16 at 19:43
  • This question really needs to be closed. It already has answers at the link I posted, and there are other resources that show how to do the exact same thing on other sites as well. – markasoftware Feb 24 '16 at 02:18
  • Dont be sore because someone downvoted your answer. – dopatraman Feb 24 '16 at 03:02

4 Answers4

14

In Node 10.x, the Readable.from convenience method was added, making this far more straightforward to accomplish.

const Readable = require('stream').Readable;

Readable.from('hello').pipe(process.stdout);
3

If your end goal is to turn a string into a readable stream, simply use the module into-stream.

var intoStream = require('into-stream')
intoStream('my-str').pipe(process.stdout)

If on the other hand, you want to know a way to actually do this yourself, the source code for that module is a little bit obtuse and so I'll create an example:

(You don't actually need a transform stream as in your code, just a writable stream)

var chars = 'my-str'.split('')
  , Stream = require('stream').Readable

new Stream({ read: read }).pipe(process.stdout)

function read(n) {
  this.push(chars.shift())
}

Note. This will only work with Node version >= 4. Previous versions didn't have the convenience methods in the Stream constructor. For older Nodes (0.10.x, 0.12.x etc.) the following slightly longer example will work…

var chars = 'my-str'.split('')
  , Stream = require('stream').Readable
  , s = new Stream()

s._read = function (n) {
  this.push(chars.shift())
}

s.pipe(process.stdout)
Ben Gourley
  • 129
  • 3
3

What you need as you say yourself is a readable stream not a transformation stream. Additionally you have a bug because string.split('') always return the same Array and then .shift() will always return the same letter. Your code once rewritten is as follows:

'use strict'

Readable = require('stream').Readable

stringer = (string) ->
  array = string.split('')
  new Readable
    read: (size) ->
      @push array.shift()
      return

readable = stringer('hello')

readable.on 'readable', ->
  console.log 'readable'
  return

readable.pipe process.stdout
yeiniel
  • 2,416
  • 15
  • 31
1

This code seems to work. I'm not really familiar with all the new JavaScript syntax in ES6 and ES7 that you're using in your question, so I just rewrote this from scratch:

const util=require('util');
const stream=require('stream');

var StringStream=function(strArg){
    stream.Readable.call(this);
    this.str=strArg.split('');
}

util.inherits(StringStream,stream.Readable);

StringStream.prototype._read=function(numRead){
    this.push(this.str.splice(0,numRead).join(''));
}

var thisIsAStringStream=new StringStream('this-is-test-text-1234567890');
thisIsAStringStream.pipe(process.stdout);

On my system it outputs this-is-test-text-1234567890, so it is working correctly. This works exactly how it is recommended in the documentation , by creating a class that extends the stream.Readable class using util.inherit, calling the constructor of stream.Readable inside of the constructor for the new class by doing stream.Readable.call('this'), and implementing the _read method to output characters from the string using this.push.

In case it's not clear, the way you would use this is by creating the stream using something like this:

var helloWorldStream=new StringStream('HelloWorld');

And then you can use the stream as you would any readable stream.

markasoftware
  • 12,292
  • 8
  • 41
  • 69
  • 1
    I've found examples like this that use inheritance, its too mangled of a solution. Is there a functional approach to using streams? Something along the lines of, `require('stream')(string).push('hello').pipe(process.stdout)`? – dopatraman Feb 23 '16 at 19:20
  • This is literally the official way to create a custom readable stream. I might look into something later today, but yeah. – markasoftware Feb 23 '16 at 23:52