web-dev-qa-db-ja.com

応答を終了する前にデータを出力するにはどうすればよいですか?

これが私が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_の前に出力されるかどうかをテストできます。私の経験ではそうではありませんが。

パケットでデータを送信するなど、応答を終了する前にデータを出力する方法はありますか?

24
Adam

コンテンツタイプをtext/plainに変更した場合-例:

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

その後、Firefoxはコンテンツをすぐに表示します。 Chromeはまだバッファリングしているようです(さらに多くのコンテンツを書き込むと、chromeはすぐに表示されます)。

16
Geoff Chappell

実際には、_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サーバーへの他のリクエストをブロックしていることに注意してください。
2つの異なるタブでこのページ(localhost:8888)の呼び出しを開くと、これを簡単にテストできます。 1つは10秒間待機し、もう1つは最初の応答が終了したときにのみ応答の開始を取得します(つまり、応答の開始を10秒間待機し、応答の終了までさらに10秒間待機します。このコード)。

おそらく、いくつかのnodejsプロセスを実行し、それらの間で負荷分散を行うことで、この障害を乗り越えることができますが、これははるかに複雑になり始め、他の場所で実行する必要があるスレッドです... :)

16
gillyb

チャンクされたプレーンテキストを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欠陥: 転送-チャンク化されたエンコーディングはテキスト/プレーンではサポートされていません

11
Vlad

注意が必要な主なポイントは次のとおりです。

  • 文字セットを指定する
  • 各「チャンク」は、ブラウザ(少なくとも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);
3
Jürgen Paul