2011-07-22 8 views
32

Estoy usando el marco de juego, para generar una respuesta fragmentada. El código es:¿Cómo escribir javascript en el lado del cliente para recibir y analizar la respuesta `chunked` a tiempo?

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 del navegador para visitar http://localhost:9000/test/chunk, puedo ver los datos mostraron un aumento 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 apareció después de 10 segundos, cuando todos los datos recibidos.

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

Respuesta

58

jQuery no soporta eso, sino que puede hacer eso con XHR claro:

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

Esto funciona en all modern browsers, incluyendo IE 10. especificación W3C here.

El inconveniente 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.

+2

¿por qué es mejor utilizar ArrayBuffer? – 4esn0k

+0

@ 4esn0k: por ejemplo, si decide usar un protocolo binario, lo cual es una buena idea. Otro punto aquí es que el navegador no tiene que mantener todos los datos en la memoria, y por lo que yo entiendo, es más fácil de lograr con 'ArrayBuffer' que con un' String'. 'slice' debería funcionar mejor, ya que no tiene que funcionar con UTF-8 String como' substring', pero puede usar índices de matriz. –

+0

ver https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType – 4esn0k

0

el evento 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 poder implementar un evento nativo onreadystatechanged y ver los paquetes de datos tal como vienen.

+1

'onreadystatechanged' sólo se disparará en el tiempo de espera, abortar y la solicitud exitosa hecho. No disparará en trozos. –

+0

k. no sabía que se llama – kishu27

+0

'onreadystatechange' cada vez que cambia la propiedad' readystate'. –

3

Pronto deberíamos poder usar ReadableStream API (MDN docs here). El código de abajo 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(); 
     }); 
    } 
}); 
Cuestiones relacionadas