Как я могу выводить данные до того, как закончу ответ?
Вот мой фрагмент, который я тестировал в 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
. По моему опыту, хотя это не так.
Есть ли способ вывода данных перед завершением ответа, что-то вроде отправки данных в пакетах?
Ответы
Ответ 1
Если вы измените тип контента на text/plain - например:
// Write Headers
response.writeHead(200, {'Content-Type': 'text/plain'});
то firefox немедленно покажет содержимое. Хром по-прежнему кажется буферным (если вы пишете больше контента, хром покажет его сразу).
Ответ 2
Фактически вы можете сделать это без установки 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 и балансировку нагрузки между ними, но затем это начинает усложняться и является потоком, который следует принимать иначе, где...:)
Ответ 3
Если вы хотите вывести chunked plain text в 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: Передача-кодировка помечена не поддерживается по тексту/plain
Ответ 4
Вот основные моменты, которые необходимо учитывать:
- укажите кодировку
- каждый "кусок" будет выводиться браузером (по крайней мере, что я заметил в Chrome) через новую строку (
<br>
, если charset - 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);