Javascript pipe(stream of Node.js)和bl(BufferList)是如何协同工作的?

Javascript pipe(stream of Node.js)和bl(BufferList)是如何协同工作的?,javascript,node.js,stream,pipe,Javascript,Node.js,Stream,Pipe,这实际上是Node.js教程([)中的第8个练习 目标: 编写一个程序,对作为第一个命令行参数提供给您的URL执行HTTP GET请求。从服务器收集所有数据(不仅仅是第一个“数据”事件),然后向控制台(stdout)写入两行数据 您写入的第一行应该是一个整数,表示从服务器接收的字符数。第二行应该包含服务器发送的完整字符串 这是我的解决方案(它通过了,但与官方解决方案相比看起来更难看) 官方解决方案: var http = require('http') var bl = require('bl'

这实际上是Node.js教程([)中的第8个练习

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

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

这是我的解决方案(它通过了,但与官方解决方案相比看起来更难看)

官方解决方案:

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)
    }))
})
我很难理解官方解决方案是如何工作的。我主要有两个问题:

  • bl构造函数希望第二个参数是 bl(根据bl模块的文件, [), 但什么是数据?它不知从何而来。它应该是未定义的 当它被传递来构造bl实例时

  • 什么时候是
    bl.end()
    调用?我看不出哪里调用了
    bl.end()

  • 希望有人能解释这些问题。(我知道我应该读源代码,但你知道…)


    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())   
    }))
    
    请注意,当您像这样使用回调方法时,结果 数据参数是数据库中所有缓冲区对象的串联 如果您想避免这种连接的开销(在 极端性能意识的情况下),然后避免回调 方法,只需听“end”,就像标准流一样

    您正在将a传递给bl,这基本上是一个函数,当它有数据流要处理时,它将调用该函数。因此,数据目前尚未定义…它只是一个参数名,稍后将用于传递GET调用中的文本以进行打印


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

    我已经阅读了
    bl
    库和的源代码

    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()
    将返回连接
    BufferList
    中所有缓冲区的结果,
    数据
    参数来自何处

    var request=require('request')
    request(process.argv[2],function(err,response,body){
    console.log(body.length);
    console.log(body);
    })
    
    你可以看看这个方法来解决上面的练习,
    p、 s的请求是第三方模块,尽管

    谢谢!事实上,我不好,我应该更仔细地阅读文档。1)数据参数用作输出参数,bl不要求它是bl的实例。(这里的描述误导了我2)对于end()调用,它确实应该由stream.pipe()调用
    BufferList.prototype.end = function (chunk) {
      DuplexStream.prototype.end.call(this, chunk)
    
      if (this._callback) {
        this._callback(null, this.slice())
        this._callback = null
      }
    }
    
    var request=require('request')
    request(process.argv[2],function(err,response,body){
    console.log(body.length);
    console.log(body);
    })