pipe(Node.jsstream)和bl(BufferList)如何一起工作?
这实际上是Node.js教程([ https://github.com/workshopper/learnyounode][1] )的第8号练习。
目标:编写一个执行HTTP GET请求的程序作为第一个命令行参数提供给您的URL。 从服务器收集所有数据(不只是第一个“数据”事件),然后写两行到控制台(标准输出)。
你写的第一行应该是一个整数,表示从服务器接收的字符数。 第二行应包含服务器发送的完整string。
所以这是我的解决scheme (它通过,但看起来比官方的解决scheme丑)。
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(); }); });
官方解决scheme:
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) })) })
我很难理解官方解决scheme的工作原理。 我主要有两个问题:
-
bl构造函数期望第二个参数是bl的一个实例(根据bl模块的文档,[ https://github.com/rvagg/bl#new-bufferlist-callback–buffer–buffer-array-] [2 ] ),但是数据是什么? 它从哪里来。 当它被传递来构造BL实例时,它应该是未定义的。
-
什么时候
bl.end()
被调用? 我可以看到没有bl.end()
被称为…
希望有人能够对这些问题提出一些看法。 (我知道我应该阅读源代码,但你知道…)
[1]: https://github.com/workshopper/learnyounode [2]: https://github.com/rvagg/bl#new-bufferlist-callback--buffer--buffer-array-
这部分的blitub页面或多或less地回答你的问题:
在构造函数中给它一个callback,并像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()) }))
请注意,当您使用这种callback方法时,生成的数据参数是列表中所有Buffer对象的串联。 如果你想避免这种连接的开销(在极端的性能意识的情况下),那么避免callback方法,而只是倾听'结束',而不是像标准的stream。
你正在向bl传递一个callback函数,这基本上是一个函数,当它有一个数据stream来处理时,它会调用它。 因此,数据现在是未定义的…它只是一个参数名称,稍后将用于传递来自GET调用的文本进行打印。
我相信bl.end()没有被调用,因为没有真正的性能开销让它运行,但我可能是错的。
我已经阅读了bl
库和节点streamAPI的源代码。
BufferList
是一个自定义的双工stream,既可读readableStream.pipe(BufferList)
写。当运行readableStream.pipe(BufferList)
,默认情况下,当源stream发出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
的callback将在BufferList
从BufferList
接收到所有数据后调用,调用此this.slice()
将返回连接BufferList
中所有缓冲区的结果,其中data
参数来自哪里。
var request=require('request') request(process.argv[2],function(err,response,body){ console.log(body.length); console.log(body); })
你可以看看这个方法来解决上面的练习,ps请求是第三方模块