Progreso de AJAX y PHP Loop en wordpress

5 minutos de lectura

avatar de usuario
Obmerk Kronen

Intento hacer algún tipo de indicador de progreso para un bucle php simple.

Hay muchas preguntas de ajax / php aquí con respecto al progreso y los bucles de php, pero después de leer muchas de ellas, todavía no puedo implementar (ni entender exactamente) la lógica.

La mayoría de ellos están hablando de -subir- barra de progreso o están demasiado localizados en un caso específico (o eso, o no sé cómo elegir las palabras clave correctas para buscar).

Mi objetivo final es hacer una barra de progreso, pero para empezar, probé un pequeño bucle de eco.

Intenté lo siguiente:

formulario html:

<p class="submit">
    <input type="submit" class="button-primary" id="o99_sudi_do_now" value="<?php _e('DO IT NOW !', 'o99_sudi_domain'); ?>" />
    <img src="https://stackoverflow.com/questions/13377455/<?php echo admin_url("/images/wpspin_light.gif'); ?>" class="waiting" id="o99_sudi_loading" style="display:none;"/>
</p>

            <div id="o99_sudi_results"></div>

jQuery

jQuery(document).ready(function($){
  jQuery('#o99_sudi_do_now_form').click(function(e){
    e.preventDefault();
    jQuery.post(ajaxurl,{action:'o99_random_loop'}, function(data){
      jQuery('#o99_sudi_results').empty().append( data );
    });
  });
});

PHP

function o99_random_loop_cb(){
 for ($i = 0; $i < 10; $i++) {
        //ob_end_clean(); // [TESING]
        echo '-- step' .$i . ' of 10</br>';
        //flush();// [TESING]
        //usleep(100000000000*0.1); // total time 10 sec.// [TESING]
        //ob_flush();// [TESING]
        usleep(20000);
    }
  die();

y dado que todo está en un área de administración de wordpress,

add_action( 'wp_ajax_o99_random_loop', 'o99_random_loop_cb' ); 

la resultado (o salida) es:

-- Step 0 of 10
-- Step 1 of 10
-- Step 2 of 10
-- Step 3 of 10
-- Step 4 of 10
-- Step 5 of 10
-- Step 6 of 10
-- Step 7 of 10
-- Step 8 of 10
-- Step 9 of 10

lo cual está bien, pero el problema es que la salida llega y el div se actualiza solo cuando finaliza la ejecución, y quiero que se actualice sobre la marcha, paso a paso… (mi bucle real planificado es bastante largo y tomará alrededor de 2-3 segundos para la iteración).

Como puedes ver con el código, lo he intentado flush(); , ob_flush(); y cualquier otra sugerencia que haya visto, pero sospecho que la LÓGICA está mal aquí (¿porque es wordpress? flush(); – el resultado llega solo cuando la función está TERMINANDO ..

Mi objetivo es hacer una barra de progreso, pero por ahora, incluso la ayuda con un simple progreso de eco será genial.

avatar de usuario
davidethell

No puede lograr lo que quiere con un solo POST a PHP. Incluso si vacía su salida de PHP, el lado de jQuery no procesará el controlador de resultados hasta que se complete todo el proceso de PHP. Hace mucho tiempo, podía obtener algo como este comportamiento solo con algunos navegadores (Netscape, etc.) que comenzaban a mostrar contenido antes de que se completara el documento; sin embargo, con AJAX no verá ninguno de los contenidos resultantes de PHP hasta que se complete el script PHP. acabado.

De ahí la razón por la que está obteniendo toda su salida a la vez.

Hay algunas formas posibles de lograr lo que quieres hacer. Un método es dividir su bucle PHP en etapas para que solo se ejecute una parte del bucle cada vez. Luego podría ejecutar algunas iteraciones (o incluso una iteración) y devolver ese resultado al navegador. Luego, el navegador mostraría el resultado y llamaría a PHP nuevamente para la próxima iteración (o conjunto de iteraciones). Si bien esto le daría su indicador de progreso, ralentizaría drásticamente su operación general y no se recomienda.

EDITADO para eliminar el uso de SESSION que no funcionará debido a problemas de concurrencia:

Otra opción es hacer que PHP guarde el progreso de su ciclo en una base de datos y hacer que el navegador sondee regularmente otro script PHP que verifique la base de datos para determinar el progreso. En un bucle rápido, esto no será tan útil, pero en un bucle de ejecución más larga, podría funcionar. Entonces, junto con su llamada $.post, comenzará una serie de llamadas $.get cronometradas para verificar el progreso.

EDITAR: Aquí hay algunos fragmentos para ilustrar:

// variable to control polling logic
var pollInterval;
// Your current post logic here with the addition of a variable to stop execution of the polling process
jQuery.post(ajaxurl,{action:'o99_random_loop'}, function(data){
    // post is complete so stop execution
    window.clearInterval(pollInterval);
});
// Now start a get process to get the progress every 5 seconds
pollInterval = window.setInterval(function () {
    // I'm assuming pollingurl is the URL to your PHP script that checks the progress
    jQuery.get(pollingurl, function(data){
        jQuery('#o99_sudi_results').empty().append( data );
    });
}, 5000);

Asumiré por ahora que en el lado de PHP se siente cómodo guardando su progreso en una tabla de base de datos y recuperando dicho progreso de la tabla.

  • hola.. gracias por la respuesta, es algo de lo que sospechaba. pero, ¿puede mostrar un pequeño ejemplo de cómo lograrlo con mi ciclo de demostración simple o tal vez un enlace a un tutorial sobre esa técnica? tal vez JS? después de todo, he visto algunos complementos que lo hacen, pero no pude descifrar cómo exactamente.

    – Obmerk Kronen

    14 de noviembre de 2012 a las 11:29

  • Ok, actualicé el ejemplo con algunos JS para demostrar. Tenga en cuenta que cambié mi respuesta para usar una base de datos en PHP en lugar de SESIONES porque PHP bloqueará la SESIÓN durante la POST y no podrá leerla hasta que se complete. Por lo tanto, debe usar algo que no esté bloqueado por el proceso POST para su encuesta.

    – davidethell

    14 de noviembre de 2012 a las 11:56

¿Ha sido útil esta solución?