stream.Transform究竟如何在Node中运行?

时间:2016-09-02 10:04:08

标签: javascript node.js express constructor prototype

下面是我在博客上找到的代码片段,其中包含一个使用Stream Transform类来改变数据流并输出更改结果的简单示例。关于这方面的一些事情,我真的不明白。

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

// node v0.10+ use native Transform, else polyfill
var Transform = stream.Transform ||
  require('readable-stream').Transform;

为什么程序需要检查this var是否指向Upper构造函数的实例? Upper构造函数用于构造下面的上层对象,那么检查这个的原因是什么?此外,我尝试了日志选项,但它返回null / undefined,那么该参数的重点是什么?

function Upper(options) {
  // allow use without new
  if (!(this instanceof Upper)) {
    return new Upper(options);
  }

我假设这个Transform.call方法正在显式设置这个变量?但是为什么程序会这样做,看看如何永远不会调用Transform。

  // init Transform
  Transform.call(this, options);
}

在谷歌搜索工具包之后,我知道这里使用它来允许Upper继承Transform的原型方法。是对的吗?

util.inherits(Upper, Transform);

以下功能让我感到困惑。据我所知,该程序正在设置Upper的原型方法,该方法用于转换输入到其中的数据。但是,我根本没有看到这个函数被调用的地方!

Upper.prototype._transform = function (chunk, enc, cb) {
  var upperChunk = chunk.toString().toUpperCase();
  this.push(upperChunk);
  cb();
};


// try it out - from the original code
var upper = new Upper();
upper.pipe(process.stdout); // output to stdout

通过调试器运行代码后,我可以看到upper.write调用前面提到的Upper.prototype._transform方法,但为什么会这样呢? upper是Upper构造函数的一个实例,而write是一个方法,似乎与应用于Upper原型的_transform方法没有任何关系。

upper.write('hello world\n'); // input line 1
upper.write('another line');  // input line 2
upper.end();  // finish

1 个答案:

答案 0 :(得分:3)

首先,如果您还没有,请查看转化流实施者的文档here

  • 问:为什么程序需要检查此var是否指向Upper构造函数的实例? Upper构造函数用于构造下面的上层对象,那么检查这个的原因是什么?

  • 答:需要检查,因为任何人都可以在没有 Upper()的情况下拨打new 。因此,如果用户检测到用户在没有new的情况下调用了构造函数,方便(并使工作正常),则代表用户隐式调用new

  • 问:此外,我尝试了记录选项,但它返回null / undefined,那么该参数的重点是什么?

  • A: options只是一个构造函数/函数参数。如果你没有向构造函数传递任何东西,那么显然它将是undefined(或者你传递给它的任何值)。您可以拥有任意数量的参数,就像任何普通函数一样。但是在Upper()的情况下,由于转换的简单性(仅将所有输入转换为大写),因此不需要配置。

  • 问:我假设这个Transform.call方法正在显式设置这个变量?但是为什么程序会这样做,看看变形从未被调用过。

  • 答:不,Transform.call()允许继承的"类"执行自己的初始化,例如设置内部状态变量。您可以将其视为在ES6课程中调用super()

  • 问:在Google搜索工具包后,我知道在这里使用它来允许Upper继承Transform的原型方法。是吗?

  • A:是的,这是正确的。但是,现在您还可以使用ES6类来进行实际继承。 node.js stream implementers documentation显示了两种继承方法的示例。

  • 问:以下功能让我感到困惑。我知道该程序正在设置Upper的原型方法,该方法用于转换输入到其中的数据。但是,我根本不知道这个函数的调用位置!

  • A:当您有要处理的数据时,此功能由节点在内部调用。可以将该方法视为接口的一部分(或者是#34;纯虚函数"如果您熟悉C ++),则需要在自定义转换中实现该方法。

  • 问:通过调试器运行代码后,我可以看到upper.write调用上述的Upper.prototype._transform方法,但为什么会这样呢? upper是Upper构造函数的一个实例,而write是一个似乎与应用于Upper原型的_transform方法无任何关系的方法。

  • A:Transform documentation所述,转换流只是简化双工流(意味着它们接受输入并产生输出)。当您调用.write()时,您正在写入Transform流的Writable(输入)端。这就是使用刚刚传递给._transform()的数据触发对.write()的调用的内容。当您调用.push()时,您正在写入Transform流的可读(输出)端。当您在转换流上调用.read()或附加'data'事件处理程序时,会看到该数据。