remove ejemplo disabled attribute jquery ajax javascript-events long-polling http-streaming

ejemplo - jquery set value input



jQuery leyĆ³ la secuencia AJAX de forma incremental? (5)

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, asuma 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.


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 here ).

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):

<!-- jquery >= 1.5. maybe earlier too but not sure --> <script src=https://code.jquery.com/jquery-1.5.min.js></script> <script> /* One-time setup (run once before other code) * adds onreadystatechange to $.ajax options * from https://gist.github.com/chrishow/3023092) * success etc will still fire if provided */ $.ajaxPrefilter(function( options, originalOptions, jqXHR ) { if ( options.onreadystatechange ) { var xhrFactory = options.xhr; options.xhr = function() { var xhr = xhrFactory.apply( this, arguments ); function handler() { options.onreadystatechange( xhr, jqXHR ); } if ( xhr.addEventListener ) { xhr.addEventListener( "readystatechange", handler, false ); } else { setTimeout( function() { var internal = xhr.onreadystatechange; if ( internal ) { xhr.onreadystatechange = function() { handler(); internal.apply( this, arguments ); }; } }, 0 ); } return xhr; }; } }); // ----- myReadyStateChange(): this will do my incremental processing ----- var last_start = 0; // using global var for over-simplified example function myReadyStateChange(xhr /*, jqxhr */) { if(xhr.readyState >= 3 && xhr.responseText.length > last_start) { var chunk = xhr.responseText.slice(last_start); alert(''Got chunk: '' + chunk); console.log(''Got chunk: '', chunk); last_start += chunk.length; } } // ----- call my url and process response incrementally ----- last_start = 0; $.ajax({ url: "https://code.jquery.com/jquery-1.5.js", // whatever your target url is goes here onreadystatechange: myReadyStateChange }); </script>


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 documentation bastante buena .


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

<!DOCTYPE> <html> <head> <title>Flushed ajax test</title> <meta charset="UTF-8" /> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> </head> <body> <script type="text/javascript"> var last_response_len = false; $.ajax(''./flushed-ajax.php'', { xhrFields: { onprogress: function(e) { var this_response, response = e.currentTarget.response; if(last_response_len === false) { this_response = response; last_response_len = response.length; } else { this_response = response.substring(last_response_len); last_response_len = response.length; } console.log(this_response); } } }) .done(function(data) { console.log(''Complete response = '' + data); }) .fail(function(data) { console.log(''Error: '', data); }); console.log(''Request Sent''); </script> </body> </html>

¿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 sintaxis 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:

<?php header(''Content-type: application/octet-stream''); // Turn off output buffering ini_set(''output_buffering'', ''off''); // Turn off PHP output compression ini_set(''zlib.output_compression'', false); // Implicitly flush the buffer(s) ini_set(''implicit_flush'', true); ob_implicit_flush(true); // Clear, and turn off output buffering while (ob_get_level() > 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:

<script src="http://code.jquery.com/jquery-1.6.4.js"></script> <script src="https://raw.github.com/ilinsky/xmlhttprequest/master/XMLHttpRequest.js"></script> <script> $(function() { var xhr = new XMLHttpRequest(); xhr.open(''GET'', ''/longpoll/'', true); xhr.send(null); var timer; timer = window.setInterval(function() { if (xhr.readyState == XMLHttpRequest.DONE) { window.clearTimeout(timer); $(''body'').append(''done <br />''); } $(''body'').append(''state: '' + xhr.readyState + ''<br />''); console.log(xhr.responseText); $(''body'').append(''data: '' + xhr.responseText + ''<br />''); }, 1000); }); </script>

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


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.