Как спроектировать интерфейс AJAX для отображения индикатора выполнения на основе запущенной серверной части скрипта - PullRequest
0 голосов
/ 31 июля 2011

Хорошо, вот моя проблема.

  1. У меня есть файл, который выводит XML на основе ввода X
  2. У меня есть другой файл, который вызывает вышеупомянутый (1) файл с 10000 (я имею в виду много раз) с разными номерами для X

Когда пользователь нажимает кнопку «Перейти», он должен пройти все эти 10000 X и одновременно показать ему прогресс в том, сколько сделано. (хм может обновляться каждые 10 секунд).

Как мне это сделать? Мне нужны идеи. Я знаю, как AJAX и все такое, но какую структуру должна принимать моя программа?

EDIT

Итак, согласно ответу, приведенному ниже, я сохранил свои выходные данные в переменной сеанса. Затем выводит ответ. То, что происходит:

Когда я выполняю скрипт loong. Это выполняется, скажем, в течение 1 минуты. Но в то же время, если я открою (в новом окне) только файл, который выводит мою переменную SESSION, то он не выдаст первый скрипт. Что полностью противоположно тому, что я хочу. В чем здесь проблема? Это моя система / сервер, который не обрабатывает несколько запросов или что?

РЕДАКТИРОВАТЬ 2

Я использую файловый подход: Читать то, что я хочу

> <?php include_once '../includeTop.php'; echo
> util::readFromLog("../../Files/progressData.tmp"); ?>

и в другом скрипте

$processed ++;
util::writeToLog($dir.'/progressData.tmp', "Files processed: $processed");

где функции:

   public static function writeToLog($file,$data) {
        $f = fopen($file,"w");
        fwrite($f, $data);
        fclose($f);
    }
    public static function readFromLog($file) {
        return file_get_contents($file);
    }

Но все еще сохраняется та же проблема :(. Я могу видеть, как файл обновляется, как 1, 2, 3 и т. Д. Но когда я запускаю свой скрипт для выполнения из php, он просто ждет, пока мой исходный скрипт будет выведен.

РЕДАКТИРОВАТЬ 3

Хорошо, я наконец нашел решение. Вместо того, чтобы искать вывод из php-файла, я прямо сейчас захожу в журнал и ищу его.

Ответы [ 2 ]

3 голосов
/ 31 июля 2011

Поместите прогресс (т. Е. Как далеко вы во 2-й файл) в memcached непосредственно из фонового задания, затем передайте это значение, если запрошено приложением javascript (запускается таймером, пока вы не достигли 100%). Единственное, что вам нужно выяснить, это как передать своего рода «идентификатор транзакции» как фоновому заданию, так и стороне javascript, чтобы они обращались к одному и тому же ключу в memcached.

1 голос
/ 31 июля 2011

Редактировать: Я был не прав насчет $_SESSION. Он не обновляется асинхронно, т. Е. Значения, которые вы храните в нем, недоступны до тех пор, пока сценарий не завершится. Упс.

Таким образом, прогресс должен храниться в чем-то, что обновляется асинхронно: в памяти (как предлагает пироскоп и, тем не менее, является лучшим решением), в файле или базе данных.

Другими словами, вместо использования $_SESSION для хранения значения, оно должно храниться в memcached, в файле или в базе данных.

т.е. используя базу данных

$progress = 0;
mysql_query("INSERT INTO `progress` (`id`, `progress`) VALUES ($uid, $progress)");
# loop starts
    # processing...
    $progress += $some_increment;
    mysql_query("UPDATE `progress` SET `progress`=$progress WHERE `id`=$uid");
# loop ends

Или используя файл

$progress = 0;
file_put_contents("/path/to/progress_files/$uid", $progress);
# loop starts
    # processing...
    $progress += $some_increment;
    file_put_contents("/path/to/progress_files/$uid", $progress);
# loop ends

А затем прочитайте файл / выберите из базы данных, когда запрашиваете прогресс через ajax. Но это не очень хорошее решение по сравнению с memcached.

Кроме того, не забудьте удалить строку файла / базы данных, как только все это будет сделано.


Вы можете поместить прогресс в переменную $_SESSION (вам понадобится уникальное имя) и обновлять его во время выполнения процесса. Между тем ваш ajax-запрос просто получает эту переменную через определенный интервал

function heavy_process($input, $uid) {
    $_SESSION[$uid] = 0;
    # loop begins
        # processing...
        $_SESSION[$uid] += $some_increment;
    # loop ends
}

Затем укажите URL, который просто выплевывает значение $_SESSION[$uid] при запросе через ajax. Затем используйте возвращенное значение, чтобы обновить индикатор выполнения. Используйте что-то вроде sha1(microtime()), чтобы создать $ uid

Редактировать: решение Pyroscope технически лучше, но если у вас нет сервера с memcached или возможностью запускать фоновые процессы, вы можете использовать $_SESSION вместо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...