节点流:等待数据可用

时间:2017-04-03 18:47:56

标签: javascript node.js node-streams

我有3个流(A,B,C),它们用管道输送到另一个流中(A-> B-> C)。 当我开始我的程序时,B的#read得到了立即调用,因为它是通过管道传输到C.然而,B-stream中没有数据,因为A取数据异步。一旦B接收到传递给B的_write方法的数据,它就会转换数据并发出一个“可读”的数据。事件(我手动触发 - 这是所谓的做法吗?)。

然而没有任何事情发生,B的数据也没有被任何人消耗(因此B&#sread不被调用)。我可以通过在_write()方法的末尾调用(在B上)this._read()来解决这个问题。但是这可能也会将数据推送给消费者,尽管队列已满,对吧?

基本上我想将更大块的数据发送到B流中,将其拆分成更小的数据,然后将它们逐个传递给C.所以我想在B中有一些缓冲区。

_read(size) {
    if(this._lineBuffer.length > 0) {
        var stop = false;
        while(!stop) {
            stop = this.push(this._lineBuffer.splice(0,1));
        }
    }
    if(this._pendingWriteAck) {
        this._pendingWriteAck();
        this._pendingWriteAck = null;
    }
}

_write(chunk, encoding, callback) {
    console.log("New chunk for line splitter received");
    if(this._buffer) {
        this._buffer = Buffer.concat([this._buffer, chunk]);
    } else {
        this._buffer = chunk;
    }
    for (; this._offset < this._buffer.length; this._offset++) {
        if (this._buffer[this._offset] === 0x0a) { // 0x0a is a new line
            this._lineBuffer.push(this._buffer.slice(0, this._offset).toString());
            this._buffer = this._buffer.slice(this._offset + 1);
            this._offset = 0;
        }
    }

    if(this._lineBuffer.length > this._maxLineBuffer || this._buffer.length > this._maxRawBuffer) {
        console.log("Line Split buffer has reached capacity. Waiting...");
        this._pendingWriteAck = callback;
    } else {
        callback();
    }

    setImmediate(()=>{
        this.emit('readable');
        this._read();
    })
}

1 个答案:

答案 0 :(得分:0)

您可以为&#34; B&#34;使用转换流。流:

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

const B = new Transform({
  transform(chunk, encoding, callback) {
    this._offset = this._offset || 0;
    this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk
    for (; this._offset < this._buffer.length; this._offset++) {
      if (this._buffer[this._offset] === 0x0a) { // 0x0a is a new line
        if (this._offset) {
          this.push(this._buffer.slice(0, this._offset), encoding);
        }
        this._buffer = this._buffer.slice(this._offset + 1);
        this._offset = 0;
      }
    }
    callback()
  },
  flush(callback) {
    if (this._buffer && this._buffer.length) {
      this.push(this._buffer);
    }
    callback();
  }
});

您可以通过执行以下操作来查看它:

let line = 0
B.on('data', (chunk) => process.stdout.write(`${++line}. ${chunk}\n`))
B.write(['Foo', 'Bar', 'Baz', 'Qux', 'Hello '].join('\n'))
B.write(['World', 'The End'].join('\n'))
B.end()

终端的输出将是:

1. Foo
2. Bar
3. Baz
4. Qux
5. Hello World
6. The End