过滤node.js中的Stream对象

时间:2011-08-04 15:35:19

标签: javascript-events node.js streaming

在我看来,在Node.js中处理某些类型数据的优雅方法是链接处理对象,如UNIX管道。

例如,grep:

function Grep(pattern) {
    ...
}
util.inherits(Grep, stream.Stream);

Grep.prototype.???? = ???????  // What goes here?

grep = new Grep(/foo/);

process.stdin.pipe(grep);
myStream.pipe(process.stdout);

然而,我并不清楚如何覆盖各种Stream方法以使其工作。

如何创建简单地从输入复制到输出的Stream对象?据推测,更复杂的过滤流可能变得微不足道。

更新:感觉好像以下内容应该有效(用CoffeeScript表示,所以我不用JS语法填充此框!):

class Forwarder extends stream.Stream
    write: (chunk, encoding) ->
        @emit 'data', chunk
    end: (chunk, encoding) =>
        if chunk?
            @emit 'data', chunk
        @emit 'end'

fwd = new Forwarder()
fwd.pipe(process.stdout);
process.stdin.pipe(fwd);
process.stdin.resume();

然而,在此脚本中捕捉到的内容不会输出任何内容。在脚本中显式调用'fwd.write()'会导致stdout输出。

2 个答案:

答案 0 :(得分:8)

你非常亲密。

因为您使用的是非常低级的流类,所以需要设置流可写属性以使其成为可写流。如果您正在从流中读取,则需要设置可读属性。此结束事件也没有任何参数。

class Forwarder extends stream.Stream
  constructor: ->
    @writable = true
  write: (chunk, encoding) ->
    @emit 'data', chunk
  end: ->
    @emit 'end'

fwd = new Forwarder()
fwd.pipe(process.stdout);
process.stdin.pipe(fwd);
process.stdin.resume();

更新

以上答案适用于Node< = 0.8中的V1流。如果您使用> 0.8,Node添加了更多旨在扩展的特定类,因此你可以使用更像这样的东西:

class Forwarder extends stream.Transform
    _transform: (chunk, encoding, callback) ->
      this.push(chunk);
      callback();

处理chunk并推送您真正想要的部分。

答案 1 :(得分:3)

虽然存在的答案很好,但仍需要代表那些寻找答案的人进行一些挖掘。

以下代码使用Node 0.10流API完成了OP提供的示例。

var stream = require('stream')
var util = require('util')

function Grep(pattern) {
  stream.Transform.call(this)

  this.pattern = pattern
}

util.inherits(Grep, stream.Transform)

Grep.prototype._transform = function(chunk, encoding, callback) {
  var string = chunk.toString()

  if (string.match(this.pattern)) {
    this.push(chunk)
  }

  callback()
}

var grep = new Grep(/foo/)
process.stdin.pipe(grep)
grep.pipe(process.stdout)