2013-07-18 80 views
0

我搞砸了Node.js 0.10 Stream類,試圖弄清楚如何使用它們。我不確定爲什麼這個實驗不起作用。它應該將字母表的字母輸出到HTTP響應對象,但不是。我已經註釋了一些評論的來源。這個程序爲什麼不輸出任何數據?

謝謝!

var Readable = require('stream').Readable 
    , inherits = require('util').inherits 
    , http = require('http'); 

/** 
* A stream that streams the English alphabet 
*/ 

function AlphabetStream() { 
    Readable.call(this); 
    this.code = this.offset = 'a'.charCodeAt(0); 
    this.last = 'z'.charCodeAt(0); 
} 

inherits(AlphabetStream, Readable); 

AlphabetStream.prototype._read = function(size) { 
    for (var i = 0; i < size; i++) 
    this.push(this.next_char()); 
    this.push(null); 
}; 

AlphabetStream.prototype.next_char = function() { 
    var cycle = this.last+1; 
    return String.fromCharCode((++this.code % cycle) + this.offset); 
}; 


/** 
* An HTTP server, prints the first n letters of the English alphabet 
*/ 

var server = http.createServer(function(req, res) { 
    // $ curl localhost:3001/?size=11 

    var size = require('url').parse(req.url, true).query.size; 

    if (size) { 
    var rs = new AlphabetStream; 
    rs.pipe(res); // This calls `_read()` with `size` 16kb 
    rs.read(parseInt(size)); // This also calls `_read()` with `size` 16kb 
    } 

    res.end(''); // Nothing gets printed, despite the pipe and the reading. 
}); 

server.listen(3001, function() { 
    console.log('Listening on 3001'); 
}); 

回答

3

看一看這段代碼:實際管道之前

if (size) { 
    var rs = new AlphabetStream; 
    rs.pipe(res); // This calls `_read()` with `size` 16kb 
    rs.read(parseInt(size)); // This also calls `_read()` with `size` 16kb 
} 

res.end(''); // Nothing gets printed, despite the pipe and the reading. 

你最終的答覆(最後一行)可以發生(出現這種情況是因爲.pipe是異步的)。你應該做的是這樣的事情:

if (size) { 
    var rs = new AlphabetStream; 
    rs.pipe(res); 
    rs.read(parseInt(size)); 
} else { 
    // NOTE THE ELSE STATEMENT 
    res.end(''); 
} 

.pipe功能會照顧結束在目的地流(即響應),除非明確地聲明,否則,請參閱文檔:

http://nodejs.org/api/stream.html#stream_readable_pipe_destination_options

編輯至於爲什麼16kb?那麼,我不得不做一些測試,似乎這是.pipe的默認行爲(我不知道如何改變這一點,說實話)。首先要注意的是:

rs.read(parseInt(size)); 

是完全沒用的(你可以刪除它)。 .pipe將負責讀取數據。現在默認行爲是讀取16kb的數據塊。因此,爲了做你正在嘗試做你應該通過sizeAlphabetStream構造,像這樣:

function AlphabetStream(size) { 
    Readable.call(this); 
    this.code = this.offset = 'a'.charCodeAt(0); 
    this.last = 'z'.charCodeAt(0); 
    this.size = size; // <--- store size here 
} 

inherits(AlphabetStream, Readable); 

AlphabetStream.prototype._read = function(size) { 
    // this allows the stream to be a true stream 
    // it reads only as much data as it can 
    // but .read can be called multiple times without issues 
    // with a predefined limit 

    var chunk = Math.min(size, this.size); 
    this.size -= chunk; 
    for (var i = 0; i < chunk; i++) { 
    this.push(this.next_char()); 
    } 
    if (!this.size) { 
    // end the stream only when the limit is reached 
    this.push(null); 
    } 
}; 

所有流之後,不應當取決於你有多少數據讀取。那麼你這樣做:

if (size) { 
    var rs = new AlphabetStream(parseInt(size)); 
    rs.pipe(res); 
} else { 
    res.end(''); 
} 
+0

感謝澄清如何'.pipe()'照顧結束流。爲什麼'_read'中的'size'最終不管我的實際輸入是16k? –

+0

@dimadima我已經更新了答案。 – freakish

相關問題