Прогресс AJAX и PHP Loop в wordpress

Я пытаюсь сделать какой-то индикатор прогресса для простого цикла php.

Здесь есть много вопросов по ajax/php, касающихся прогресса и циклов php, но после читая их много, я до сих пор не могу реализовать (и точно понять) логику..

Большинство из них либо говорят о -upload- индикаторе выполнения, либо слишком привязаны к конкретному случаю (либо так, либо я не знаю, как выбрать правильные ключевые слова для поиска).

Моя конечная цель — сделать индикатор выполнения, но для начала я попробовал небольшой эхо-цикл.

Я пробовал следующее:

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="<?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();

и так как все это находится в административной области WordPress -

add_action( 'wp_ajax_o99_random_loop', 'o99_random_loop_cb' ); 

результат (или вывод):

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

это нормально, но проблема в том, что вывод поступает, и div обновляется только после завершения выполнения - и я хочу, чтобы он обновлялся на лету, шаг за шагом... (мой реальный запланированный цикл довольно долго и займет около 2-3 секунд для итерации. )

Как вы можете видеть в коде, я пробовал flush();, ob_flush(); и любые другие предложения, которые я видел, но я подозреваю, что ЛОГИКА здесь неверна (потому что это wordpress?? или сброс в неправильном месте?) и на самом деле нет независимо от того, сколько я flush(); - результат приходит только тогда, когда функция ЗАВЕРШАЕТСЯ..

Моя цель сделать прогресс бар - а пока даже помощь с простым эхом прогресса будет здорово..


person Obmerk Kronen    schedule 14.11.2012    source источник


Ответы (1)


Вы не можете достичь того, чего хотите, с помощью одного POST для PHP. Даже если вы сбросите свой вывод PHP, сторона jQuery не будет обрабатывать обработчик результатов, пока весь процесс PHP не будет завершен. Давным-давно вы могли получить что-то подобное этому только с некоторыми браузерами (Netscape и т. д.), которые начинали отображать содержимое до того, как документ был завершен, однако с AJAX вы не увидите никакого результирующего содержимого из PHP до тех пор, пока скрипт PHP не будет законченный.

Следовательно, причина, по которой вы получаете всю свою продукцию сразу.

Есть несколько возможных способов выполнить то, что вы хотите сделать. Один из способов — разбить цикл PHP на этапы, чтобы каждый раз выполнялась только часть цикла. Затем вы можете выполнить несколько итераций (или даже одну итерацию) и вернуть этот результат в браузер. Затем браузер отобразит результат и снова вызовет PHP для следующей итерации (или набора итераций). Хотя это даст вам индикатор прогресса, это значительно замедлит вашу общую работу и не рекомендуется.

EDITED для удаления использования SESSION, который не будет работать из-за проблем с параллелизмом:

Другим вариантом является сохранение PHP хода выполнения вашего цикла в базу данных, а сторона браузера регулярно опрашивает другой PHP-скрипт, который проверяет базу данных, чтобы определить ход выполнения. В быстром цикле это будет не так уж полезно, но в более длинном цикле это может сработать. Таким образом, вместе со своим вызовом $.post вы начнете серию синхронизированных вызовов $.get для проверки прогресса.

РЕДАКТИРОВАТЬ: Вот несколько фрагментов для иллюстрации:

// 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);

На данный момент я предполагаю, что на стороне PHP вам удобно сохранять свой прогресс в таблице базы данных и извлекать указанный прогресс из таблицы.

person davidethell    schedule 14.11.2012
comment
привет .. спасибо за ответ, это то, что я подозревал. но не могли бы вы продемонстрировать небольшой пример того, как этого добиться с помощью моего простого демонстрационного цикла, или, может быть, ссылку на учебник по этой технике? может ЖС? в конце концов, я видел некоторые плагины, которые делают это, но я не мог понять, как именно. - person Obmerk Kronen; 14.11.2012
comment
Хорошо, я обновил пример, добавив немного JS для демонстрации. Примечание. Я изменил свой ответ, чтобы использовать базу данных на PHP вместо SESSIONS, потому что PHP заблокирует SESSION во время POST, и вы не сможете прочитать его, пока он не завершится. Поэтому вам нужно использовать что-то, что не заблокировано процессом POST для вашего опроса. - person davidethell; 14.11.2012