2015-06-18 19 views
9

Jest to właściwie No.8 ćwiczenia z samouczka node.js ([https://github.com/workshopper/learnyounode][1])W jaki sposób potok (strumień Node.js) i bl (BufferList) współpracują ze sobą?

Cel: Napisz program, który wykonuje żądania HTTP GET do URL dostarczonych do was jako pierwszy Command argument linii. Zbierz wszystkie dane z serwera (nie tylko pierwsze zdarzenie "data"), a następnie napisz dwie linie do konsoli (stdout).

Pierwsza wpisana linia powinna być po prostu liczbą całkowitą reprezentującą liczbę znaków otrzymanych z serwera. Drugi wiersz powinien zawierać kompletny ciąg znaków wysłany przez serwer.

Oto moje rozwiązanie (Przekazuje, ale wygląda gorzej w porównaniu do oficjalnego rozwiązania).

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

Oficjalna rozwiązanie:

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

mam trudności ze zrozumieniem, jak działa oficjalna rozwiązanie. Mam głównie na dwa pytania:

  1. BL konstruktor spodziewa 2. Argument być instancją bl (zgodnie z dokumentacją bl modułu, [https://github.com/rvagg/bl#new-bufferlist-callback--buffer--buffer-array-][2]), ale to, co jest dane? Pojawił się znikąd. Powinien być niezdefiniowany kiedy zostanie przekazany do konstruowania instancji bl.

  2. kiedy jest bl.end() nazywany? Widzę, że nie ma gdzie bl.end() nazywa ...

nadzieję, że ktoś może rzucić nieco światła na te pytania. (Wiem, że powinienem już odczytać kodu źródłowego, ale wiesz ...)

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

Odpowiedz

6

Ta część strony bl github mniej więcej odpowiada na pytanie:

nadać mu zwrotnego w konstruktorze i używać go tak jak 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()) 
})) 

pamiętać, że podczas korzystania z metody wywołania zwrotnego tak, otrzymany parametr danych jest połączeniem wszystkich obiektów bufor w th e lista. Jeśli chcesz uniknąć narzutów tej konkatenacji (w przypadkach o ekstremalnej wydajności), unikaj metody oddzwaniania i po prostu słuchaj "końca", jak standardowy strumień.

Podajesz callback dla bl, która jest w zasadzie funkcją, którą wywoła, gdy ma strumień danych do zrobienia czegoś. Tak więc dane są na razie niezdefiniowane ... to tylko nazwa parametru, która później posłuży do przekazania tekstu z wywołania GET do drukowania.

Wierzę, że bl.Funkcja end() nie została wywołana, ponieważ nie ma realnego obciążenia, aby pozwolić jej działać, ale mogę się mylić.

+0

chodzi 'end', zobacz tutaj - https://github.com/rvagg/bl # ctor – levi

+0

Dzięki! W rzeczy samej, moje złe, powinienem uważniej przeczytać dokument. 1) parametr danych jest używany jako parametr wyjściowy, a bl nie wymaga, aby był instancją bl. (Byłem wprowadzony w błąd przez opis tutaj https://github.com/rvagg/bl#new-bufferlist-callback--buffer--buffer-array- – slowreader239

+0

2) Dla wywołania end(), w rzeczywistości ma się nazywać przez stream.pipe() https://nodejs.org/api/stream.html#stream_readable_pipe_destination_options – slowreader239

3

Przeczytałem kod źródłowy biblioteki bl i node stream API.

BufferList jest strumień zwyczaj duplex, czyli zarówno czytelny i Writable.When uruchomieniu readableStream.pipe(BufferList) domyślnie end() nazywa na BufferList jako miejsca docelowego, gdy strumień źródło emituje end() który uruchamia się, gdy nie będzie więcej danych do odczytu .

Zobacz implementation z 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 
    } 
} 

Więc zwrotna przekazywana do BufferList, będzie nazwane po BufferList otrzymał wszystkie dane ze strumienia materiałów wsadowych, zadzwoń this.slice() zwróci wynik złączenie wszystkich buforów w BufferList Skąd pochodzi parametr data.

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

można rzucić okiem na tego podejścia w celu rozwiązania powyższego ćwiczenia, prośba ps jest modułem osoba trzecia chociaż

Powiązane problemy