Как я могу вывести данные, прежде чем закончить ответ?

Вот мой фрагмент, который я тестировал в 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);
Другие вопросы по тегам