Коротко о насущном: есть задача, отображать прогресс выполнения PHP скрипта на странице сайта. Тема достаточно интересная, с учетом того, что в основном своем при переходе или при обновлении элемента люди обновляют страницу. Конечно, это совсем не удобно, и да - это решается при помощи AJAX. Глядя со стороны все тривиально: первый AJAX запрос запускает скрипт, а второй запрашивает статус прогресса. Естественно, этот статус нужно где-то хранить. И первое, что приходит на ум - сессии. Уверен, что все движки на PHP их используют, а если это не движок, тогда тоже не страшно, их можно включить функцией session_start.
Вот на этом месте я бы, на месте читателя, задался вопросом: "Если все так просто, зачем писать статью?". Да, вопрос вполне корректный. Но статья ради одной изюминки, за которую мне пришлось немного побороться.
test_sleep.php
test_progress.php
index.html
Вот на этом месте я бы, на месте читателя, задался вопросом: "Если все так просто, зачем писать статью?". Да, вопрос вполне корректный. Но статья ради одной изюминки, за которую мне пришлось немного побороться.
Все дело в сессиях!
Когда я написал 3 скрипта (тестовый скрипт PHP, который создавал видимость загрузки; PHP скрипт, который возвращал прогресс выполнения; HTML страница с двумя JavaScript функциями, которые отправляли AJAX запрос на оба эти скрипта), то увидел, что "все плохо" - оба запроса отправляются и я получаю результат, но не сам процесс. Другими словами, при нажатии кнопки, стартующей скрипт с эмуляцией загрузки мне ничего не говорил, а скрипт, который запрашивал прогресс возвращал только конечный результат в 100%. Конечно, это не то, чего мне хотелось.Затянул с развязкой!
Итак, дело в сессиях! Когда запускался скрипт с эмуляцией, он стартовал сессию и записывал в нее статус прогресса. Поскольку он использует цикл в своей основе, то и запись значения в сессию производилась на каждой итерации. Сессия стартовала, в нее производится запись, но мы стартуем второй скрипт, который считывает данные из сессии. И вот она кульминация, второй скрипт не может считать данные из сессии, поскольку первый скрипт продолжает в нее писать. Решение есть! В этом нам поможет другой оператор session_write_close. Он не закрывает, не останавливает и не убивает сессию, он просто говорит, что сессия закрыта на запись и можно ее читать.Много слов, а где же практика?
Ниже я привожу все 3 скрипта, которые работают.test_sleep.php
/** * Цикл для эмуляции загрузки */ for ($i = 1; $i <= 10; $i++) { /** * Стартуем сессию */ session_start(); /** * Записываем значение прогресса в переменную сессии */ $_SESSION['ls_sleep_test'] = $i * 10; /** * Закрываем сессию на запись */ session_write_close(); /** * Ждем 1 секунду */ sleep(1); } /** * Выходим из скрипта */ exit();
test_progress.php
/** * Стартуем сессию */ session_start(); /** * Выводим значение прогресса */ echo isset($_SESSION['ls_sleep_test']) ? $_SESSION['ls_sleep_test'] : ''; /** * Выходим из скрипта */ exit();
index.html
<script type="text/javascript">function ls_ajax_test() { /** * Переменная интервала. * Будем запускать функцию опроса результата прогресса каждую секунду * @type object */ var myVar = setInterval(function() { ls_ajax_progress(); }, 1000); /** * Выполняем AJAX запрос к скрипту эмуляции */ $.ajax({ type: 'POST', url: '/services/test_sleep.php', success: function(data) { /** * По завершению работы скрипта эмуляции останавливаем таймер * опроса прогресса * @returns {Boolean} */ clearInterval(myVar); /** * В результирующий тег пишем результат * @returns {Boolean} */ $('#progress').html('DONE'); }, }); /** * На всякий случай вернем FALSE * @returns {Boolean} */ return false; } function ls_ajax_progress() { /** * Выполняем AJAX запрос к скрипту опроса результата прогресса * @returns {Boolean} */ $.ajax({ type: 'POST', url: '/services/test_progress.php', success: function(data) { /** * В реультирующий тег пишем то, что вернул скрипт */ $('#progress').html(data); }, }); /** * На всякий случай вернем FALSE * @returns {Boolean} */ return false; }</script> <!--Кнопочка старта--> <input type="button" class="btn btn-primary" value="START" onclick="return ls_ajax_test(); return false;" /> <div id="progress"> <!--Результат прогресса--> Progress </div>
Спасибо Вам!
ОтветитьУдалитьСпасибо за Вашу статью.
ОтветитьУдалитьзапросы срабатывают последовательно, то есть только итоговый прогресс видно
ОтветитьУдалить