节点 - 将管道步骤抽象为函数

时间:2017-02-20 19:00:57

标签: node.js stream pipe node.js-stream through2

我熟悉节点流,但我正在努力寻找抽象代码的最佳实践,我将其重复使用到一个管道步骤中。

这是我今天写的一个精简版:

inputStream
.pipe(csv.parse({columns:true})
.pipe(csv.transform(function(row) {return transform(row); }))
.pipe(csv.stringify({header: true})
.pipe(outputStream);

实际工作发生在transform()。唯一真正改变的是inputStreamtransform()outputStream。就像我说的,这是我实际使用的精简版。我有很多错误处理和登录每个管道步骤,这最终是我尝试抽象代码的原因。

我想写的是一个单步管步骤,如下所示:

inputStream
.pipe(csvFunction(transform(row)))
.pipe(outputStream);

我正在努力理解的是如何将这些管道步骤转换为接受流并返回流的单个函数。我已经看过像2这样的图书馆,但是我不知道如何让我到达我想去的地方。

2 个答案:

答案 0 :(得分:2)

您可以像这样使用PassThrough类:

var PassThrough = require('stream').PassThrough;

var csvStream = new PassThrough();
csvStream.on('pipe', function (source) {
  // undo piping of source
  source.unpipe(this);
  // build own pipe-line and store internally
  this.combinedStream =
    source.pipe(csv.parse({columns: true}))
      .pipe(csv.transform(function (row) {
        return transform(row);
      }))
      .pipe(csv.stringify({header: true}));
});

csvStream.pipe = function (dest, options) {
  // pipe internal combined stream to dest
  return this.combinedStream.pipe(dest, options);
};

inputStream
  .pipe(csvStream)
  .pipe(outputStream);

答案 1 :(得分:0)

这就是我最终的目标。我使用through2库和streaming API of the csv library来创建我正在寻找的管道功能。

var csv = require('csv');
    through = require('through2');

module.exports = function(transformFunc) {
    parser = csv.parse({columns:true, relax_column_count:true}),
    transformer = csv.transform(function(row) {
        return transformFunc(row);
    }),
    stringifier = csv.stringify({header: true});

    return through(function(chunk,enc,cb){
        var stream = this;

            parser.on('data', function(data){
                transformer.write(data);
            });

            transformer.on('data', function(data){
                stringifier.write(data);
            });

            stringifier.on('data', function(data){
                stream.push(data);
            });

            parser.write(chunk);

            parser.removeAllListeners('data');
            transformer.removeAllListeners('data');
            stringifier.removeAllListeners('data');
            cb();
    })
}

值得注意的是我在最后删除事件监听器的部分,这是由于遇到内存错误,我创建了太多的事件监听器。我最初尝试通过使用once监听事件来解决此问题,但这会阻止后续块被读取并传递到下一个管道步骤。

如果有人有反馈或其他想法,请告诉我。