管道(Node.js流)和bl(BufferList)如何协同工作?

slo*_*239 10 javascript pipe stream node.js

这实际上是Node.js教程中的练习No.8([ https://github.com/workshopper/learnyounode] [1 ])

目标: 编写一个程序,对作为第一个命令行参数提供给您的URL执行HTTP GET请求.收集服务器中的所有数据(不仅仅是第一个"数据"事件),然后将两行写入控制台(stdout).

您编写的第一行应该是一个整数,表示从服务器接收的字符数.第二行应包含服务器发送的完整字符串.

所以这是我的解决方案(它通过但看起来比官方解决方案更丑).

var http = require('http'),
bl = require('bl');

var myBL = new bl(function(err, myBL){
    console.log(myBL.length);
    console.log(myBL.toString());
});

var url = process.argv[2];
http.get(url, function(res){
    res.pipe(myBL);
    res.on('end', function(){
        myBL.end();
    });
});
Run Code Online (Sandbox Code Playgroud)

官方解决方案:

var http = require('http')
var bl = require('bl')

http.get(process.argv[2], function (response) {
    response.pipe(bl(function (err, data) {
        if (err)
            return console.error(err)
        data = data.toString()
        console.log(data.length)
        console.log(data)
    }))
})
Run Code Online (Sandbox Code Playgroud)

我很难理解官方解决方案的工作原理.我主要有两个问题:

  1. bl构造函数期望第二个参数是bl的一个实例(根据bl模块的文档,[ https://github.com/rvagg/bl#new-bufferlist-callback--buffer--buffer-array-] [2 ]),但什么是数据?它突然冒出来了.传递给构造bl实例时,它应该是未定义的.

  2. 何时被bl.end() 召唤?我看不出那个bl.end()被称为......

希望有人可以对这些问题有所了解.(我知道我应该阅读源代码,但你知道......)

  [1]: https://github.com/workshopper/learnyounode
  [2]: https://github.com/rvagg/bl#new-bufferlist-callback--buffer--buffer-array-
Run Code Online (Sandbox Code Playgroud)

小智 6

bl github页面的这一部分或多或少回答了你的问题:

在构造函数中给它一个回调并像concat-stream一样使用它:

const bl = require('bl')
, fs = require('fs')

fs.createReadStream('README.md')   
   .pipe(bl(function (err, data) { //  note 'new' isn't strictly required
      // `data` is a complete Buffer object containing the full data
      console.log(data.toString())   
}))
Run Code Online (Sandbox Code Playgroud)

请注意,当您使用这样的回调方法时,结果数据参数是列表中所有Buffer对象的串联.如果你想避免这种连接的开销(在极端性能意识的情况下),那么避免使用回调方法而只是听一下'end',就像标准的Stream一样.

你正在将一个回调传递给bl,它基本上是一个函数,当它有一个数据流来执行某些操作时它将调用.因此,数据现在尚未定义...它只是一个参数名称,稍后将用于传递来自GET调用的文本以进行打印.

我相信bl.end()没有被调用,因为没有真正的性能开销让它运行,但我可能是错的.