Задать вопрос
seoperin
@seoperin
Full stack web developer. Laravel / Vue

Прогресс выполнения php foreach в ajax запросе?

Есть страница с ajax запросом к php файлу.
$(document).ready( function () {
	$("#button").click(function () {

		var name = $('#name').val();

		if ( name != "") {
			$('.loading').removeClass('hidden');
			$.ajaxSetup({
			  headers: {
			    'X-CSRF-TOKEN': $('#csrf-token').val()
			  }
			});
			$.ajax({
			  url: "ajax2",
			  type: "POST",
			  dataType: "json",
			  data: {'name' : name},
			  success: function(data){
			    $('#msg').html(data.message);
			  }
			}).done(function(data) {
		      $('#content').text(data.message);
		    });
		} else {
			$('#msg').html('Введите имя');
			$('.loading').addClass('hidden');
		}

	});
});

Примерно так делаю запрос, а так обрабатываю (laravel)
for ($i=0; $i <= 30000000; $i++) { 
	$message = $i;
}
return json_encode(['message' => 'Элементов: '. $message. '. Имя: ' .$request->get('name')]);

Собственно вопрос, как в блоке #progress выводить прогресс выполнения foreach?
  • Вопрос задан
  • 3238 просмотров
Подписаться 14 Оценить Комментировать
Решения вопроса 3
GogElf
@GogElf
Хокаге
По средством создания постоянного соединения и отправкой оповещений через него (comet).
Ответ написан
Taraflex
@Taraflex
Ищу работу. Контакты в профиле.
Для такого придумали https://learn.javascript.ru/server-sent-events
но в ie оно похоже уже никогда не появится
caniuse.com/#feat=eventsource
Ответ написан
shukshinivan
@shukshinivan
веб-разработчик
Если прогресс реально очень долгий, можно запускать второй процесс, который бы опрашивал текущий статус обработки. Пример такой реализации был на хабре https://habrahabr.ru/post/153731/ . Там демо не работает, вот демо по этой же идее: www.plus2net.com/php_tutorial/progress-bar2-demo.php
Ну и где-то видел заминусованный вариант, где аякс выдавал дивы-полосочки общего прогресса и флашил их. Вот, нашёл: stackoverflow.com/questions/20453015/progress-bar-... Дурная, но идея.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
@Fellowship
Все варианты, предложенные здесь подразумевают установку дополнительного ПО или использования иных технологий.

Но на самом деле можно обойтись и без них.

Смотрите.
У Laravel есть замечательный механизм кронджобов. Используйте его в связке с mysql.

Допустим у нас есть таблица с тасками для выполнения в фоне с 4мя полями
id, task, progress, result
(я уже правда не помню структуру таблицы laravel у кроновых тасков)

И ajax запрос первый будет лишь командой на вставку новой задачи, который на js возвращает лишь id таска.

Далее на клиенте реализовываем второй запрос - проверка статуса. Сам запрос просто запрашивает из базы значение поля progress из базы, а Js, например, рисует красивый прогресс. И пускай он с интервалом раз в секунду или несколько секунд (в зависимости от задачи) опрашивает сервер.

Далее реализовываем третий запрос - получение результата. Как только на второй запрос получили ответ, что таск выполнен на 100%, отправляем запрос на получение результата который берет его из базы (или из redis, или из сессии, короче из любого хранилища. Если сайт не нагружен можно и в базе хранить в сериализованном виде).

А сам соответственно таск пускает выполняется себе в фоне и никого не трогает. Если это vds или dedicated то на такие процессы вообще можно поставить ограничения и по памяти и по нагрузки на проц, или вообще вынести на отдельный docker или виртуальный контейнер. Короче, поле для деятельности масса.

Плюсы такого варианта:
  • не нужно использовать современные технологии типа websoket (по их незнанию или по нежеланию или просто отсутствию возможности)
  • Поддержка браузеров явно больше чем у WebSocket (wikipedia)
  • достаточно использовать только встроенные технологии laravel
  • не требует сторонних библиотек


Минусы данного подхода:
  • Все таки действительно 21 век на носу и можно уже изучить WebSocket
  • Требует постоянного опроса сервера, хоть нагрузка и небольшая от них, но все таки нагрузка
  • Вопрос с хранением результатов остается открытым для очень больших запросов и при высокой нагрузке
Ответ написан
Комментировать
thecoder
@thecoder
Разработчик веб-приложений и сервисов.
Вот обзор методов как асинхронно получать сообщения с сервера (вышеупомянутый комет - один из вариантов): stackoverflow.com/questions/11077857/what-are-long...

Раньше делал врукопашную через веб-сокеты. Сейчас можно интеллигентнее.

Вот хорошая обертка вокруг вебсокетов, реализующая паттерн подписки на события: wamp-proto.org Перед отправкой тяжелого аякс запроса, клиент устанавливает вебсокет-соединение и подписывается на событие "обновление %". Серверная часть внутри цикла отсылает сообщения подписчикам.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы