jQuery leyó la secuencia AJAX de forma incremental?

He leído esta pregunta pero no responde exactamente mi pregunta. Desafortunadamente, parece que las cosas han cambiado en el objeto XHR desde la última vez que miré a AJAX, por lo que ya no es posible acceder directamente a responseText antes de que termine de completarse.

Tengo que escribir una página que utiliza AJAX (preferiblemente jQuery, pero estoy abierto a sugerencias) para recuperar datos CSV a través de HTTP desde un servidor que no tengo control. Los datos de respuesta podrían ser bastante grandes; un megabyte de texto no es raro.

El servidor es amigable para la transmisión. ¿Todavía hay alguna manera de obtener acceso a una secuencia de datos a medida que se devuelve, directamente desde JavaScript?

Tengo la opción de escribir algún código PHP que viva en el medio y use algún tipo de tecnología “Comet” (larga encuesta, EventSource, etc.), pero preferiría evitar eso si es posible.

En caso de que sea relevante, asum para esta pregunta que los usuarios tienen la última versión de Firefox / Chrome / Opera y que la compatibilidad con el viejo navegador no es un problema.

Vas a querer utilizar Javascript para esto. La razón es que vas a querer sondear continuamente y no esperar a que se activen las devoluciones de llamada. No necesitas jQuery para esto, es bastante simple. Tienen un buen código fuente para esto en el sitio web Ajax Patterns .

Esencialmente, solo querrá hacer un seguimiento de su última posición en la respuesta y sondear periódicamente para obtener más texto después de esa ubicación. La diferencia en su caso es que puede suscribirse al evento completo y detener su votación.

Esto es bastante sencillo cuando se envía texto o HTML . A continuación hay un ejemplo.

(Sin embargo, te encontrarás con problemas si tratas de generar JSON , que abordaré más adelante).

ARCHIVO PHP

 header('Content-type: text/html; charset=utf-8'); function output($val) { echo $val; flush(); ob_flush(); usleep(500000); } output('Begin... (counting to 10)'); for( $i = 0 ; $i < 10 ; $i++ ) { output($i+1); } output('End...'); 

ARCHIVO HTML

    Flushed ajax test        

¿Qué pasa si necesito hacer esto con JSON?

En realidad, no es posible cargar un solo objeto JSON de forma incremental (antes de que esté completamente cargado) porque hasta que tenga el objeto completo, la syntax siempre será inválida.

Pero si su respuesta tiene múltiples objetos JSON, uno tras otro, entonces es posible cargar uno a la vez, a medida que descienden por la tubería.

Así que modifiqué mi código de arriba por ...

  1. Cambiando PHP FILE línea 4 de echo $val; para echo '{"name":"'.$val.'"};' . Esto produce una serie de objetos JSON.

  2. Cambiar la línea 24 de ARCHIVOS HTML desde console.log(this_response); a

     this_response = JSON.parse(this_response); console.log(this_response.name); 

    Tenga en cuenta que este código rudimentario supone que cada "fragmento" que llega al navegador es un objeto JSON válido. Esto no siempre será así porque no puede predecir cómo llegarán los paquetes; es posible que deba dividir la cadena en puntos y coma (o crear otro carácter separador).

No use la application/json

NO para cambiar los encabezados a la application/json - Hice esto y me hizo buscar en Google durante 3 días. Cuando el tipo de respuesta es application/json , el navegador espera hasta que se complete la respuesta, ya que está completo. La respuesta completa es luego analizada para verificar si de hecho es JSON. Sin embargo, nuestra respuesta COMPLETA es {...};{...};{...}; que NO es válido JSON. El método jqXHR.done supone que hubo un error porque la respuesta completa no se puede analizar como JSON.

Como se mencionó en los comentarios, puede desactivar esta verificación en el lado del cliente usando:

 $.ajax(..., {dataType: "text"}) 

Espero que algunas personas lo encuentren útil.

Use XMLHttpRequest.js

https://github.com/ilinsky/xmlhttprequest

http://code.google.com/p/xmlhttprequest

  • Ofrece una implementación discreta y discreta compatible con estándares (W3C) entre navegadores del objeto XMLHttpRequest 1.0
  • Corrige TODAS las peculiaridades de los navegadores observadas en sus implementaciones nativas de objetos XMLHttpRequest
  • Permite el registro transparente de la actividad del objeto XMLHttpRequest

Para usar encuestas largas con PHP:

output.php:

  0) { // Get the curent level $level = ob_get_level(); // End the buffering ob_end_clean(); // If the current level has not changed, abort if (ob_get_level() == $level) break; } // Disable apache output buffering/compression if (function_exists('apache_setenv')) { apache_setenv('no-gzip', '1'); apache_setenv('dont-vary', '1'); } // Count to 20, outputting each second for ($i = 0;$i < 20; $i++) { echo $i.str_repeat(' ', 2048).PHP_EOL; flush(); sleep(1); } 

run.php:

    

Esto debería dar como resultado:

 state: 3 data: 0 state: 3 data: 0 1 state: 3 data: 0 1 2 state: 3 data: 0 1 2 3 state: 3 data: 0 1 2 3 4 ... ... ... state: 3 data: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 state: 3 data: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 state: 3 data: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 done state: 4 data: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 

Para IE, debes buscar en XDomainRequest

http://blogs.msdn.com/b/ieinternals/archive/2010/04/06/comet-streaming-in-internet-explorer-with-xmlhttprequest-and-xdomainrequest.aspx

http://msdn.microsoft.com/en-us/library/cc288060(VS.85).aspx

Como dice que su servidor es compatible con la transmisión (asíncrono) y estaba buscando una solución de jquery, ¿ha revisado el jQuery Stream Plugin ?

Es realmente fácil de usar y le permite no preocuparse realmente por nada. También tiene una documentación bastante buena .

Aquí hay una manera directa de lograr esto usando JQuery (según lo solicitado por el OP):

Primero, amplíe el objeto ajax para que admita onreadystatechange ejecutando el siguiente código desde https://gist.github.com/chrishow/3023092 (se agrega al final de esta respuesta). Luego simplemente llame a ajax usando una función onreadystatechange que verificará texto nuevo en xhr.responseText.

Si quieres ser aún más elegante, puedes borrar los datos del texto de respuesta cada vez que lo leas, como se describe aquí ).

Por ejemplo, consulte https://jsfiddle.net/g1jmwcmw/1/ , que descargará la respuesta de https://code.jquery.com/jquery-1.5.js y la publicará en fragmentos dentro de la ventana de la consola, utilizando el código a continuación (que puede copiar en una página html y luego abrir en su navegador):