Как я могу вывести данные, прежде чем закончить ответ?
Вот мой фрагмент, который я тестировал в 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 ответа
Если вы измените тип содержимого на text/plain - например:
// Write Headers
response.writeHead(200, {'Content-Type': 'text/plain'});
тогда Firefox покажет содержимое сразу. Похоже, что Chrome все еще находится в буфере (если вы напишете больше контента, Chrome покажет его сразу).
Там на самом деле есть способ, которым вы можете сделать это без настройки 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 и распределив нагрузку между ними, но затем это начинает становиться все более сложным, и это поток, который следует взять где-то еще...:)
Если вы хотите выводить фрагментированный простой текст в 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);
Вам не нужна эта опция, если ваш вывод text/html
,
Решение, найденное из этого дефекта Chrome: передача-кодирование чанковано не поддерживается на текстовом / простом
Вот основные моменты, на которые нужно обратить внимание:
- указать кодировку
- каждый "чанк" будет выводиться браузером (по крайней мере, что я заметил в 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);