12

我在网络和文档中搜索node.js express模块,似乎没有办法按部分发送数据。我的文件渲染速度不是很快,我想在渲染所有内容之前发送它的一部分。

所以这是我的问题:

  1. 有没有办法response按部分发送数据?
  2. 有什么作用response.end()
  3. 如果无法按部分发送数据 - 背后的原理是什么?如果这是真的,我会说它看起来比非阻塞更阻塞。如果更早提供数据,浏览器可以更快地加载信息。

示例简化代码:

app.get(..) {
  renderFile(file, function(data) {
    response.send(data);
  });
  response.end();
)

这段代码只发送第一块数据。我检查了 - 数据正确给出并且回调被多次调用。

当然,我可以将数据附加到一个变量然后写入response.send(data);,但我不喜欢这种方法 - 这不是它应该工作的方式。

4

5 回答 5

22

response对象是一个可写流。只需写入它,Express 甚至会自动为您设置分块编码。

response.write(chunk);

如果创建此“文件”的任何内容都将其自身呈现为可读流,您也可以通过管道传递给它。 http://nodejs.org/api/stream.html

于 2013-07-14T21:50:58.493 回答
2

实现这一点的简单方法是将数据转换为可读流并将其通过管道传输到响应对象。这是我的nodejs代码。希望这可能会有所帮助

var express= require('express');
var bodyParser = require('body-parser');
const JSONStreamStringify = require('json-stream-stringify');

var app=express();
var jsonParser = bodyParser.json();

app.post('/node_test_pipe', jsonParser, function (req, res) {
    console.log("Request from:"+req.url);
    var obj={
             my:1,
             two:2
            }
    JSONStreamStringify(obj).pipe(res);
    var obj={
             my:3,
             two:4
            }
    JSONStreamStringify(obj).pipe(res);
    });

app.listen(8080);
于 2018-06-22T18:46:20.943 回答
2

除了使用Response.write()方法来分块发送和Response.end()标记结束!

如果你有一个流!您可以将其直接通过管道传递给Response对象!一切都会自动处理!

有关文件可读流,请参见下面的示例:

var http = require('http');
var fs = require('fs');

http.createServer(function(req, res) {
  // The filename is simple the local directory and tacks on the requested url
  var filename = __dirname+req.url;

  // This line opens the file as a readable stream
  var readStream = fs.createReadStream(filename);

  // This will wait until we know the readable stream is actually valid before piping
  readStream.on('open', function () {
    // This just pipes the read stream to the response object (which goes to the client)
    readStream.pipe(res); // <====== here
  });

  // This catches any errors that happen while creating the readable stream (usually invalid names)
  readStream.on('error', function(err) {
    res.end(err);
  });
}).listen(8080);

您可以使用任何 Stream 做到这一点。只需将其通过管道传递给 Respond 对象!

上面的例子来自这里:

https://nodejs.org/en/knowledge/advanced/streams/how-to-use-fs-create-read-stream/

底线

使用管道!它也很好看和更好地理解!

这是来自文档的链接!

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

readable.pipe() 方法将Writable流附加到readable,使其自动切换到流动模式并将其所有数据推送到附加的 Writable。

并注意链接

可以将多个 Writable 流附加到单个 Readable 流。

readable.pipe() 方法返回对目标流的引用,从而可以设置管道流链

例子:

const fs = require('fs');
const r = fs.createReadStream('file.txt'); // read stream
const z = zlib.createGzip(); // write stream
const w = fs.createWriteStream('file.txt.gz'); // write stream
r.pipe(z).pipe(w);

阅读文档以获取更多信息!

于 2020-05-27T08:09:18.993 回答
1

Express 扩展了我相信扩展 HTTP 的 Connect。查看HTTP API,您似乎正在寻找的是response.write,它将一大块数据作为响应正文发送。然后我相信你可以使用response.end结束信号。

于 2013-07-14T21:52:27.133 回答
-1

可以写入响应对象。在您的情况下,以下将是一个解决方案:

renderFile(file, function(data) {
  response.send(data);
});
response.end();

如果您有机会将文件作为流获取,则可以进一步简化:

file.getReadableStream().pipe(response);
于 2014-10-23T13:52:18.267 回答