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');
});
4

1 回答 1

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 的数据块。所以为了做你想做的事情,你可能应该传递size给 的构造函数AlphabetStream,如下所示:

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('');
}
于 2013-07-18T21:58:22.757 回答