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

Ada*_*dam 23 response flush node.js

这是我在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);
Run Code Online (Sandbox Code Playgroud)

你可以看到我超时了response.end()所以我可以测试是否response.write输出之前response.end.根据我的经验,虽然不是.

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

Geo*_*ell 16

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

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

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


gil*_*lyb 15

这里实际上是一种方式,你可以做到这一点无需设置Content-Type: text/plain,并仍然使用text/htmlContent-Type,但你必须告诉浏览器期望的数据块.

这可以很容易地完成,如下所示:

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);
Run Code Online (Sandbox Code Playgroud)


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

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


小智 10

如果你想在Chrome中输出分块纯文本- 就像Firefox默认做的那样 - 你需要使用'X-Content-Type-Options': 'nosniff'标题.请参阅什么是"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);
Run Code Online (Sandbox Code Playgroud)

如果您的输出是,则不需要此选项text/html.

从此Chrome缺陷中找到的解决方案:在text/plain上不支持Transfer-Encoding