这是我在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
之前输出。但根据我的经验,情况并非如此。
有没有一种方法可以在结束响应之前输出数据,比如以数据包的形式发送数据?
实际上有一种方法可以在不设置Content-Type: text/plain
的情况下做到这一点,并且仍然使用text/html
作为Content-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);
不过,您应该知道,在调用response.end()
之前,请求仍在进行,并阻止其他对nodejs服务器的请求
您可以通过在两个不同的选项卡上打开调用此页面(localhost:8888)来轻松测试这一点。其中一个将等待10秒,另一个只有在第一个响应结束后才会得到响应的开始(这意味着使用此代码,您将等待10秒钟等待响应的开始,再等待10秒钟直到响应结束)。
您可能也可以通过运行几个nodejs进程并在它们之间进行负载平衡来克服这个障碍,但随后这开始变得更加复杂,并且是一个应该在其他地方使用的线程…:)
如果将内容类型更改为text/plain,例如:
// Write Headers
response.writeHead(200, {'Content-Type': 'text/plain'});
那么firefox将立即显示内容。Chrome似乎仍然可以缓冲(如果你写了更多的内容,Chrome会立即显示)。
如果您想在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('Beginningn');
var count = 10;
var io = setInterval(function() {
res.write('Doing ' + count.toString() + 'n');
count--;
if (count === 0) {
res.end('Finishedn');
clearInterval(io);
}
}, 1000);
}).listen(8888);
如果您的输出是text/html
,则不需要此选项。
从这个Chrome缺陷中找到的解决方案:文本/纯不支持传输编码块
以下是您需要注意的要点:
- 指定一个字符集
- 每个"chunk"将由浏览器(至少,我在Chrome中注意到的)通过一行新行(如果字符集是
text/html
,则为<br>
)输出
像这样:
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);