2015-04-10 2 views
0

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

Я начинаю с отображения «загрузочной страницы», которая вызывает вызов AJAX для большого метода обработки в моем контроллере (назовем его «P»). Затем этот метод возвращает частичное представление, и я просто заменяю содержимое «загрузочной страницы» на это частичное представление. Он работает нормально.

Теперь то, что я хотел бы сделать, это предоставить пользователю некоторую информацию об этом процессе (а позже и некоторый контроль над ним), например, сколько результатов, которые скрипт уже нашел. Для этого я делаю еще один вызов AJAX каждые 5 секунд, который должен извлекать текущее количество результатов и отображать его в простом элементе html. Этот вызов использует метод «R» в том же контроллере, что и метод «P».

Теперь проблема заключается в том, что я не могу получить правильное текущее количество результатов. Я попробовал 2 вещи:

  • Сессионная переменная ('file' driver): в 'P' Сначала я установил переменную сеанса 'v' в 0 и затем обновляю 'v' каждый раз, когда будет найден новый результат. 'R' просто возвращает response()->json(session('v'))
  • Переменная контроллера: тот же принцип, что и выше, но я использую переменную, объявленную в верхней части моего контроллера.

Звонок AJAX в 'P' работает в обоих случаях, но каждый раз и в обоих случаях он возвращает 0. Если я верну 'назад' в конце скрипта 'P', он имеет правильное значение ,

Так что мне кажется, что «R» не может получить доступ к фактическому текущему значению «v», он только получает доступ к некоторой «кешированной» версии.

У кого-нибудь есть представление о том, как я смогу достичь того, что я хотел бы сделать? Есть ли другой «более чистый» подход и/или что не так с моим?

Спасибо, хорошо провести день!

__

Некоторые псевдо-кода, мы надеемся сделать его немного более точным.

SearchController.php

function P() { 
    $i = 0; 
    session(['count' => $i]); // set session variable 
    $results = sqlQuery(); // get rows from DB 

    foreach ($results as $result) { 

     if (regexFunction($result)) 
      $i++ 

     session(['count' => $i]); // update session variable 

    } 

    return response()->json('a bunch of stuff'); 
} 

function R() { 
    return response()->json(session('count')); // always returns 0 
} 
+0

Вы используете innoDB в качестве двигателя в своей БД? – Daan

+0

Если вы хотите показать количество результатов для пользователя, вы можете просто подсчитать возвращаемые строки и меня часть вашего возвращаемого параметра с контроллера. –

+0

Я использую PostgreSQL, у которого есть собственный механизм хранения, если я правильно помню. – SynRJ

ответ

0

Я бы рекомендовал другой подход здесь. Прочтите немного больше о промывочном содержимом здесь http://php.net/manual/en/ref.outcontrol.php, а затем используйте его.

Короче говоря, чтобы отображать числа строк, обработанных с помощью промывки, вы можете просто сделать результат цикла и время от времени промывать или точным числом или строками, необходимость в 5-секундном AJAX исчезла. Малый непроверенных пример:

$cnt = 0; 
foreach($result as $key => $val) { 
    //do your processing here 
    if ($cnt % 100 == 0) { 
      //here echo smth for flushing, you can echo some javascript, tough not nice 
      echo "<script>showProcess({$cnt});</script>"; 
      ob_flush(); 
    } 
} 
// now render the proccessed full result 

И в showProcess Javascript функция делает то, что вы хотите ... некоторые JQuery заменить в тексте или какой-либо графический материал ...

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

+0

Если мне наконец удастся выполнить флеш-работу (см. Ответ ниже), у меня будет проблема, если я хочу, чтобы пользователь мог прервать процесс (для этого нужен AJAX-вызов, чтобы обновить какую-то переменную, которая делает большой процесс стоп). Мне может понадобиться решение с вызовами AJAX в любом случае, если вы можете указать мне в правильном направлении относительно этой части. – SynRJ

+0

Хмм, возможно, я говорю дерьмо, но когда процесс начинается, возможно, вы можете найти pid процесса, сохранить его в текстовом файле для каждого пользователя или smth, а затем сделать ajax-вызов, который считывает pid из этого файла и убивает нить круто ...? Жесткий, неважно, и проблемы безопасности могут расти там ... – Cosmin

0

Я считаю, что вы столкнулись с стеной с ограничениями PHP. PHP не многопоточен, ну.Чтобы достичь уровня взаимодействия, вам, вероятно, необходимо напрямую отредактировать файлы сеанса, путь которого можно найти в вашем сеансе .save_path global через php_info(), и вы можете отредактировать этот путь с помощью session_save_path(String). Хотя это не рекомендуется использовать, делайте это на свой страх и риск.

В качестве альтернативы можно использовать файл JSON TXT, хранящийся где-то на вашем компьютере/сервере, и идентифицировать их аналогично файлам сеанса.

Необходимо сохранить текущий ход запроса в файл, а также если транзакция была прервана пользователем. перед продолжением итерации по набору результатов должна выполняться проверка состояния бита прерывания/булина.

Проблема возникает, когда вы рассматриваете параллелизм, что, если булев отредактирован чуть раньше или в то же время, что и массив count? Возможно, вы просто продолжаете обновлять файл с помощью прерываний, пока другой скрипт не получит сообщение. Это, однако, не изящное решение.

Это решение не допускает одновременных запросов, выполняемых одним и тем же пользователем. для этого необходимо выполнить дополнительную проверку в файле сеанса, чтобы определить, что-то уже запущено. Следует уведомить об ошибке, чтобы уведомить пользователя.

Учитывая возможность, я бы лично, переписать код в любом JSP или ASP.NET

В целом это очень много работы для ненадежных функции.

Смежные вопросы