Как написать javascript на стороне клиента, чтобы получить и проанализировать ответ "chunked" во времени?
Я использую платформу воспроизведения, чтобы генерировать фрагментированный ответ. Код:
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 секунд, когда все полученные данные.
Как получить поток и обработать данные во времени?
Ответы
Ответ 1
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
.
Ответ 2
событие success
будет срабатывать при завершении полной передачи данных и закрытии соединения с кодом ответа 200. Я считаю, что вы должны реализовать собственное onreadystatechanged
событие и увидеть пакеты данных по мере их появления.
Ответ 3
Вскоре мы сможем использовать ReadableStream
API (MDN docs здесь). Код ниже, похоже, работает с Chrome Version 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();
});
}
});
Ответ 4
Нет, вы не можете. Механизм ответа HTTP (включая сжатие и chunking) абстрагируется от JavaScript в браузере.