在结束响应之前如何输出数据?

时间:2011-06-06 21:26:11

标签: node.js response flush

以下是我在Chrome 11和Firefox 4中测试过的代码片段:

var http = require('http');

http.createServer(function(request, response){
   // Write Headers
   response.writeHead(200);

   // Write Hello World!
   response.write("Hello World!");

   // End Response after 5 seconds
   setTimeout(function(){ 
        response.end(); 
   }, 5000);

}).listen(8000);

如您所见,我超时了response.end(),因此我可以测试response.write之前是否输出了response.end。根据我的经验,虽然不是。

有没有办法在结束响应之前输出数据,比如在数据包中发送数据?

4 个答案:

答案 0 :(得分:14)

如果您将内容类型更改为text / plain - 例如:

// Write Headers
response.writeHead(200, {'Content-Type': 'text/plain'});

然后firefox会立即显示内容。 Chrome似乎仍然缓冲(如果你写了更多内容,chrome会立即显示它。)

答案 1 :(得分:14)

实际上有一种方法可以在不设置Content-Type: text/plain但仍然使用text/html作为Content-Type的情况下执行此操作,但您需要告诉浏览器预期数据块。< / p>

这可以很容易地完成:

var http = require('http');

http.createServer(function(request, response) {

    response.setHeader('Connection', 'Transfer-Encoding');
    response.setHeader('Content-Type', 'text/html; charset=utf-8');
    response.setHeader('Transfer-Encoding', 'chunked');

    response.write('hello');

    setTimeout(function() {
        response.write(' world!');
        response.end();
    }, 10000);

}).listen(8888);


但是您应该知道,在调用response.end()之前,请求仍在发生并阻止对您的nodejs服务器的其他请求。
您可以通过在两个不同的选项卡上打开调用此页面(localhost:8888)来轻松地对此进行测试。其中一个将等待10秒,而另一个将仅在第一个响应结束后得到响应的开始(意味着您将等待10秒钟开始响应,另外10秒钟直到响应结束,使用这段代码)。

你也可以通过运行几个nodejs进程并在它们之间进行负载平衡来传递这个障碍,但是这开始变得更加复杂,并且是一个应该被带到其他地方的线程......:)

答案 2 :(得分:6)

如果您想在 Chrome 中输出分块纯文本 - 就像 Firefox 默认执行的那样 - 您需要使用'X-Content-Type-Options': 'nosniff'标题。见What is "X-Content-Type-Options=nosniff"?

var http = require('http');

http.createServer(function (req, res) {
    res.writeHead(200, {
        'Content-Type': 'text/plain; charset=utf-8',
        'Transfer-Encoding': 'chunked',
        'X-Content-Type-Options': 'nosniff'});
    res.write('Beginning\n');
    var count = 10;
    var io = setInterval(function() {
        res.write('Doing ' + count.toString() + '\n');
        count--;
        if (count === 0) {
            res.end('Finished\n');
            clearInterval(io);
        }
    }, 1000);
}).listen(8888);

如果输出为text/html,则不需要此选项。

从此Chrome缺陷中找到的解决方案:Transfer-Encoding chunked not support on text/plain

答案 3 :(得分:3)

以下是您需要注意的主要观点:

  • 指定字符集
  • 每个“块”将由浏览器输出(至少,我在Chrome中注意到的)通过新行(<br>,如果字符集为text/html

像这样:

res.setHeader('Content-Type', 'text/html; charset=utf-8');
res.write('a<br>');
setTimeout(function() {
  res.write('b<br>');
  setTimeout(function() {
    res.write('c');
    res.end();
  }, 2000);
}, 2000);