¿Cómo escribir javascript en el lado del cliente para recibir y analizar la respuesta `chunked` a tiempo?

Estoy usando Play Framework, para generar una respuesta fragmentada. El código es:

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); } } } 

Cuando uso el navegador para visitar http://localhost:9000/test/chunk , puedo ver los datos que se muestran aumentados cada segundo. Pero, cuando escribo una función de JavaScript para recibir y manejar los datos, descubro que bloqueará hasta que todos los datos recibidos.

El código es:

 $(function(){ $.ajax( "/test/chunked", { "success": function(data, textStatus, xhr) { alert(textStatus); } } ); }); 

Puedo ver un cuadro de mensaje emergente después de 10s, cuando todos los datos recibidos.

¿Cómo obtener la transmisión y manejar los datos a tiempo?

jQuery no es compatible con eso, pero puede hacerlo con XHR normal:

 var xhr = new XMLHttpRequest() xhr.open("GET", "/test/chunked", true) xhr.onprogress = function () { console.log("PROGRESS:", xhr.responseText) } xhr.send() 

Esto funciona en todos los navegadores modernos , incluida la especificación IE 10. W3C aquí .

La desventaja aquí es que xhr.responseText contiene una respuesta acumulada. Puede usar subcadena en él, pero una mejor idea es usar el atributo responseType y usar slice en un ArrayBuffer .

Pronto deberíamos poder usar la API ReadableStream ( documentos MDN aquí ). El siguiente código parece estar funcionando con la versión de 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(); }); } }); 

el evento de success se activará cuando se complete la transmisión de datos y la conexión se cierre con un código de respuesta de 200. Creo que deberías ser capaz de implementar un evento nativo onreadystatechanged y ver los paquetes de datos tal como vienen.