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



这实际上是 Node.js教程中的第 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();
    });
});

官方解决方案:

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)
    }))
})

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

  1. bl 构造函数期望第二个参数是 BL(根据BL模块的文档, [https://github.com/rvagg/bl#new-bufferlist-callback--buffer--buffer-array-][2]), 但什么是数据?它不知从何而来。它应该是未定义的 当它被传递以构造 BL 实例时。

  2. 什么时候bl.end() 叫? 我看不出bl.end()在哪里叫

  3. ...

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

  [1]: https://github.com/workshopper/learnyounode
  [2]: https://github.com/rvagg/bl#new-bufferlist-callback--buffer--buffer-array-

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

在构造函数中给它一个回调并像 连接流:

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())   
}))

请注意,当您像这样使用回调方法时,结果 data 参数是 列表。如果要避免此串联的开销(在 极端性能意识的情况),然后避免回调 方法,只需收听"结束",就像标准流一样。

你正在向 bl 传递一个回调,它基本上是一个函数,当它有数据流要做某事时,它会调用它。 因此,数据目前尚未定义...它只是一个参数名称,稍后将用于从 GET 调用传递文本以进行打印。

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

我已经阅读了bl库和节点流API的源代码。

BufferList 是自定义双工流,既是可读的,也是可写的。运行 readableStream.pipe(BufferList) 时,默认情况下,当源流发出end()时,将在 BufferList 上调用end()作为目标,当没有更多数据要读取时触发。

请参阅BufferList.prorotype.end的实现:

BufferList.prototype.end = function (chunk) {
  DuplexStream.prototype.end.call(this, chunk)
  if (this._callback) {
    this._callback(null, this.slice())
    this._callback = null
  }
}

所以传递给BufferList的回调,将在BufferList收到来自源流的所有数据后调用,调用this.slice()将返回连接data参数来自的BufferList中所有缓冲区的结果。

var request=require('request')
request(process.argv[2],function(err,response,body){
console.log(body.length);
console.log(body);
})

你可以看看这个方法来解决上面的练习,P.S请求虽然是第三方模块

相关内容

  • 没有找到相关文章

最新更新