2015-06-18 24 views
9

Questo è in realtà l'esercizio No.8 dal tutorial Node.js ([https://github.com/workshopper/learnyounode][1])In che modo pipe (stream of Node.js) e bl (BufferList) funzionano insieme?

L'obiettivo: Scrivete un programma che esegue una richiesta HTTP GET a un URL fornito a voi come il primo Comando- argomento di linea. Raccogli tutti i dati dal server (non solo il primo evento "dati") e quindi scrivi due righe sulla console (stdout).

La prima riga che scrivi dovrebbe essere solo un numero intero che rappresenta il numero di caratteri ricevuti dal server. La seconda riga dovrebbe contenere la stringa completa di caratteri inviati dal server.

Quindi ecco la mia soluzione (Passa ma sembra più brutta rispetto alla soluzione ufficiale).

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

La soluzione ufficiale:

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

ho difficoltà a capire come funziona la soluzione ufficiale. Ho principalmente due domande:

  1. Il costruttore bl si aspetta che il secondo argomento sia un'istanza di bl (secondo la documentazione del modulo bl, [https://github.com/rvagg/bl#new-bufferlist-callback--buffer--buffer-array-][2]), ma ciò che è dati? È venuto fuori dal nulla. Dovrebbe essere non definito quando viene passato per costruire l'istanza bl.

  2. quando è bl.end() chiamato? Non vedo dove che la bl.end() si chiama ...

La speranza che qualcuno possa fare luce su queste domande. (So ​​che avrei dovuto leggere il codice sorgente, ma non si sa ...)

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

risposta

6

Questa porzione della pagina GitHub bl più o meno risponde alla tua domanda:

dargli un callback nel costruttore e utilizzarlo proprio come 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()) 
})) 

si noti che quando si utilizza il metodo di callback come questo, il parametro dei dati risultante è una concatenazione di tutti gli oggetti Buffer in th e lista . Se si desidera evitare il sovraccarico di questa concatenazione (nei casi di coscienza delle prestazioni estreme), quindi evitare il callback metodo e basta ascoltare 'fine' invece, come un flusso standard.

Si sta passando a callback in bl, che è fondamentalmente una funzione che chiamerà quando ha un flusso di dati con cui fare qualcosa. Pertanto, per ora i dati non sono definiti ... è solo un nome parametro che verrà utilizzato in seguito per passare il testo dalla chiamata GET per la stampa.

Credo che bl.end() non è stato chiamato perché non c'è un reale sovraccarico delle prestazioni per farlo funzionare, ma potrei sbagliarmi.

+0

Per quanto riguarda 'FINE', vedi qui - https://github.com/rvagg/bl # ctor – levi

+0

Grazie a entrambi! Anzi, mio ​​cattivo, avrei dovuto leggere il documento con più attenzione. 1) il parametro data viene utilizzato come parametro di uscita e bl non richiede che sia un'istanza di bl. (Sono stato fuorviato dalla descrizione qui https://github.com/rvagg/bl#new-bufferlist-callback--buffer--buffer-array- – slowreader239

+0

2) Per la chiamata end(), in effetti dovrebbe essere chiamata di stream.pipe() https://nodejs.org/api/stream.html#stream_readable_pipe_destination_options – slowreader239

3

Ho letto il codice sorgente della libreria bl e node stream API.

BufferList è un flusso su due piani su misura, che è sia leggibile e Writable.When si esegue readableStream.pipe(BufferList), per impostazione predefinita end() è chiamato sul BufferList come destinazione quando il flusso sorgente emette end() che spara quando non ci saranno più dati da leggere .

Vedi l'implementation di 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 
    } 
} 

Così il callback passato a BufferList, sarà chiamato dopo BufferList ricevuti tutti i dati dal flusso di origine, chiamare this.slice() restituirà il risultato della concatenazione tutti i buffer nel BufferList da dove proviene il parametro data.

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

si può avere uno sguardo su questo approccio per risolvere l'esercizio precedente, richiesta PS è un terzo modulo parti se