チャンクされた応答を生成するために、playフレームワークを使用しています。コードは次のとおりです。
class Test extends Controller {
public static void chunk() throws InterruptedException {
for (int i = 0; i < 10; i++) {
String data = repeat("" + i, 1000);
response.writeChunk(data);
Thread.sleep(1000);
}
}
}
ブラウザを使用してhttp://localhost:9000/test/chunk
にアクセスすると、表示されるデータが毎秒増加しているのがわかります。しかし、データを受信して処理するJavaScript関数を作成すると、すべてのデータが受信されるまでブロックされることがわかりました。
コードは次のとおりです。
$(function(){
$.ajax(
"/test/chunked",
{
"success": function(data, textStatus, xhr) {
alert(textStatus);
}
}
);
});
すべてのデータを受信すると、10秒後にポップアップメッセージボックスが表示されます。
ストリームを取得して時間内にデータを処理する方法は?
jQueryはそれをサポートしていませんが、単純なXHRでそれを行うことができます。
var xhr = new XMLHttpRequest()
xhr.open("GET", "/test/chunked", true)
xhr.onprogress = function () {
console.log("PROGRESS:", xhr.responseText)
}
xhr.send()
これは、IE 10. W3C仕様 ここ を含む) すべての最新ブラウザ で機能します。
ここでの欠点はxhr.responseText
には累積応答が含まれます。部分文字列を使用できますが、 responseType 属性を使用し、slice
でArrayBuffer
を使用することをお勧めします。
まもなく、ReadableStream
API( MDN docs here )を使用できるようになります。以下のコードはChromeバージョン62.0.3202.94で動作しているようです:
fetch(url).then(function (response) {
let reader = response.body.getReader();
let decoder = new TextDecoder();
return readData();
function readData() {
return reader.read().then(function ({value, done}) {
let newData = decoder.decode(value, {stream: !done});
console.log(newData);
if (done) {
console.log('Stream complete');
return;
}
return readData();
});
}
});
success
イベントは、完全なデータ転送が完了し、接続が200応答コードで閉じられたときに発生します。ネイティブのonreadystatechanged
イベントを実装して、データパケットが到着するのを確認できるはずです。