2010-10-21 22 views
5

Estoy usando javascript para ejecutar un XMLHttpRequest a un script PHP que devuelve datos. Básicamente, quiero poder proporcionar al usuario una barra de progreso (en lugar de un círculo giratorio o algo así) que muestre el progreso de obtener y recibir los datos. Sé que si obtuviera un archivo, podría simplemente verificar el encabezado de la longitud del contenido y usarlo, pero en el caso de un script, no se sabe la cantidad de datos que está recuperando.Obteniendo XMLHttpRequest Progreso desde PHP Script

La respuesta a esto podría ser tan fácil como "no es posible", porque en este momento parece ser así. Pero en conclusión: ¿cómo se supervisa el progreso de un script en ejecución (php) y XMLHttpRequest?

+0

Puede haber una docena de formas diferentes de hacerlo. Depende de qué está haciendo el script PHP y qué tipo de tecnología del lado del servidor tiene. ¿Puedes ser mas específico? – mellowsoon

+0

La secuencia de comandos ejecuta consultas y usa los datos para generar código html, que el controlador de respuestas xmlhttprequest inserta en la página actual. – Evan4623

Respuesta

1

En la parte superior de mi cabeza puedes usar 2 solicitudes de ajax. Uno para comenzar y esperar a que se complete el trabajo, y otro para verificar el progreso del trabajo. Estoy bastante seguro de que la mayoría de los navegadores pueden hacer al menos 2 solicitudes ajax a la vez.

El script PHP (vamos a llamarlo job.php) que en realidad está haciendo el trabajo puede actualizar la variable de sesión $ _SESSION ['job_progress'] con el porcentaje del trabajo que se completa.

tiene otro script PHP (Le llaman progress.php) que hace eco de ese valor, es decir, del lado del cliente

<?php echo $_SESSION['job_progress']; 

a encender de su petición ajax a job.php. Tienes otra solicitud de ajax para progress.php que se ejecuta cada 3 segundos. Actualizas tu barra de progreso con el valor devuelto.

También podría hacer esto con una solicitud ajax si la solicitud de job.php regresa antes de que el trabajo haya finalizado. Luego puede seguir usando una única solicitud ajax para hacer ping al script progress.php.

+0

Creo que quiere saber cuántos bytes de un archivo solicitó con XHR hasta el momento. – GordonM

+0

@Gordon: se aplica el mismo concepto. – mellowsoon

+0

PHP no mantiene un registro de la cantidad de bytes que se envía a través de una conexión dada, así que no entiendo realmente cómo sería útil usar una segunda conexión para preguntar. Si desactiva PHP para ejecutar un trabajo que tardará mucho tiempo en ejecutarse, puede usar su solución para preguntar cuánto tiempo piensa antes de que se complete el trabajo, pero en el caso de un trabajo que finaliza muy rápido pero los resultados en una gran cantidad de datos que se enviarán este enfoque no funcionaría tan bien. – GordonM

0

En algunos navegadores (Firefox para uno), onreadystatechange con readyState 3 (es decir, cargando) se invoca varias veces para que se pueda controlar el progreso de la descarga.

Además, en algunos navegadores, la propiedad responseText contiene los resultados obtenidos hasta ahora, y podría examinarse para tener una idea del progreso.

Sin embargo, Internet Explorer (al menos para Internet Explorer 7, no está seguro acerca más adelante) no es compatible con esto, y es un error para consultar responseText o responseBody para readyState 3. También he oído la IE sólo llama una vez onreadystatechange con readyState 3 que lo haría bastante inútil para su propósito, pero le sugiero probarlo.

0

Crear una sesión. (Probablemente, ya tienes uno). Cree un UID para la consulta, cuando lo solicite para comenzar el procesamiento.

Almacenar en algún lugar del servidor (en la base de datos, en archivos, etc.) un progreso junto con el SID + UID, a medida que la consulta avanza.

Utilice una segunda solicitud ajax con temporizador para sondear el progreso mediante SID + UID.

* Puede obtener solo UID, probablemente, pero he encontrado que es más manejable cuando también puede monitorear tareas por usuario/sesión.

2

Si está utilizando FireFox (y estoy bastante seguro de que la mayoría de los otros navegadores aparte de IE), de hecho hay una manera de informar cuántos datos se han transferido durante una operación XHR. Si la operación en cuestión envía el encabezado correcto, es bastante fácil utilizar esta información para calcular el porcentaje de los datos descargados.

Escribí este código para determinar el porcentaje de datos transferidos en una operación XHR hace años, así que me disculpo por ello y no refleja los años de experiencia en codificación que he adquirido desde entonces. ¡Casi seguro que no lo escribiría de esta manera ahora! Aún así, logré pescarlo, y espero que te sirva.

En el momento en que esto fue escrito, IE7 era la última versión de Explorer disponible, y recuerdo que el código no funcionó en eso, por lo tanto, contiene código para evitar que se inicialice en IE. Nunca he probado este código en la versión 8 o beta de la versión 9, y de hecho también puede funcionar en esas versiones, pero no puedo responderlo. Si puede hacerlo funcionar en una nueva versión de IE, ¡por favor hágamelo saber!

Funciona mediante la ejecución de código en beforeSend (una jQuery de devolución de llamada proporciona el código que desea ejecutar antes de iniciar una solicitud ajax) para configurar un intervalo de Javascript (en el código he puesto 50 milisegundos, que probablemente sea demasiado a menudo, 200 milisegundos todavía deberían ser suficientes y ejercer menos presión sobre el sistema). Cada vez que se dispara el temporizador de intervalo, ejecuta una función que mira el atributo responseText de la solicitud XHR. El atributo responseText contiene el texto sin formato de los datos recibidos hasta el momento. Contando cuántos caracteres hay con el método de cadena length(), podemos calcular cuántos bytes se han recopilado hasta ahora.

En cuanto a calcular el porcentaje de datos totales que se enviarán, esto requerirá que su código del lado del servidor envíe un encabezado de longitud de contenido con un recuento exacto de cuántos bytes va a enviar. Esto requerirá un poco de astucia de su parte, pero no debe resultar demasiado difícil. Si envía un encabezado preciso de longitud de contenido, entonces se usa para calcular un porcentaje de los datos recibidos hasta el momento. Si no configura un encabezado de contenido, entonces se mostrará la cantidad de datos recibidos hasta el momento.

<script type="text/javascript"> 
$.ajax ({ 
    beforeSend : function (thisXHR) 
    { 
     // IE doesn't support responseText access in interactive mode 
     if (!$.browser.msie) 
     { 
      myTrigger = setInterval (function() 
      { 
       if (thisXHR.readyState > 2) 
       // When there is partial data available use it to determine how much of the document is downloaded 
       { 
        var dlBytes = thisXHR.responseText.length; 
        if (totalBytes == -1) 
         totalBytes = thisXHR.getResponseHeader ('Content-length'); 
        (totalBytes > 0)? 
         $('#progress').html (Math.round ((dlBytes/totalBytes) * 100) + "%"): 
         $('#progress').html (Math.round (dlBytes/1024) + "K"); 
       } 
      }, 50); // Check the status every 50 miliseconds 
     } 
    }, 
    complete : function() 
    { 
     // Kill the download progress polling timer 
     if (myTrigger) 
      clearInterval (myTrigger); 
    } 
}); 
</script> 
Cuestiones relacionadas