Задать вопрос
@faragly

2 angular AJAX запроса. Как получить ответ на второй запрос, пока выполняется первый?

Здравствуйте, уважаемые разработчики! Прошу помочь разобраться. Есть php функция которая работает долго (5-10 секунд), и поэтапно в данной функции срабатывает запись промежуточных данных (используется файловая БД Flintstone.php). Если запустить функцию то можно при открытом файле бд увидеть как меняются данные. Так вот на стороне клиента работает AngularJS, создается 2 ajax запроса - первый запускает большую функцию, которая будет выполняться долго и записывать промежуточные данные в БД, второй запрос отправляется через 1 секунду и работает в цикле пока не отработает скрипт.
HTML этот (при старте запрос отправляется):
<div class="container" style="padding-top:40px;" ng-app="elementSearch" ng-controller="SearchCtrl" ng-init="ajaxStart()">
		<div class="progress">
			<div class="progress-bar progress-bar-info progress-bar-striped" role="progressbar" aria-valuenow="{{progress}}" aria-valuemin="0" aria-valuemax="100" style="width: {{progress}}%">
				<span class="sr-only">{{progress}}</span>
			</div>
		</div>
		<pre>{{options}}</pre>
	</div>

Angular код приведен ниже:
'use strict';
var app = angular.module('elementSearch', ['ngResource']).controller('SearchCtrl', ['$scope', '$http', '$timeout', 'Data', function($scope, $http, $timeout, Data) {
	$scope.stopped = false;
	$scope.progress = 0;
	$scope.ajaxStart = function(){
		Data.query({action: 'start', id: '123', ajax: 'Y'}, function(data){
			$scope.stopped = data.stopped;
		});
		$timeout($scope.ajaxProgress, 1000);
	};
	$scope.ajaxProgress = function(){
		Data.query({action: 'progress', id: '123', ajax: 'Y'}, function(data){
			if(!($scope.stopped = data.stopped))
				$timeout($scope.ajaxProgress(), 1000);
			$scope.progress = (data.finished/data.totalSteps)*100;
		});
	};

}]).factory('Data', function ($resource) {
	return $resource('/steps/ajax.php', {lang: 'ru'}, {
		query: { 
			method: 'POST', 
			params: {}, 
			headers: {'Content-Type': 'application/x-www-form-urlencoded'},
			transformRequest: function(obj) {
				var str = [];
				for(var p in obj)
					str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
				return str.join("&");
			},
			responseType: 'json'
		}
	});
});

PHP код по возможности упрощен, чтобы было понятнее:
<?
define("NO_KEEP_STATISTIC", true);
define("NO_AGENT_STATISTIC", true);
define("NOT_CHECK_PERMISSIONS", true);

require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_admin_before.php");
header('Content-Type: application/x-javascript; charset='.LANG_CHARSET);

\Bitrix\Main\Loader::includeModule('my.module');
use \Flintstone\Flintstone;

if($REQUEST_METHOD == "POST" && $_REQUEST['id'])
{
	switch ($post['action']) {
		case 'start':
			if($_REQUEST['id'])
				$arResult = longFunc($_REQUEST['id']);
			echo json_encode($arResult);
			break;
		case 'progress':
			if($_REQUEST['id'])
				$arResult = getProgress($_REQUEST['id']);
			echo json_encode($arResult);
			break;
		default:
			# code...
			break;
	}
}

function longFunc($id)
{
	setProgress($id, ['step' => 1, 'finished' => 0, 'message' => 'Шаг первый', 'stopped' => false]);
	sleep(2);
	setProgress($id, ['step' => 2, 'finished' => 1, 'message' => 'Шаг второй', 'stopped' => false]);
	sleep(2);
	setProgress($id, ['step' => 3, 'finished' => 2, 'message' => 'Шаг третий', 'stopped' => false]);
	sleep(2);
	setProgress($id, ['step' => 4, 'finished' => 3, 'message' => 'Шаг четвертый', 'stopped' => false]);
	sleep(2);
	setProgress($id, ['step' => 5, 'finished' => 4, 'message' => 'Шаг пятый', 'stopped' => false]);
	sleep(2);
	setProgress($id, ['step' => 5, 'finished' => 5, 'message' => 'Завершено', 'stopped' => true]);
	return ['stopped' => true, 'data' => []];
}

function getProgress($movieId)
{
	$movieData = Flintstone::load('requests', ['dir' => __DIR__]);
	$progress = $movieData->get($movieId);
	Flintstone::unload('requests');
	return $progress;
}

function setProgress($movieId, $data)
{
	$movieData = Flintstone::load('requests', ['dir' => __DIR__]);
	$data = array_merge($data, ['totalSteps' => 5]);
	$movieData->set($movieId, $data);
	Flintstone::unload('requests');
	return true;
}

require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_after.php");
die();
?>


В общем ответ на промежуточный запрос не приходит, пока не закончится первый запрос. Помогите разобраться.
  • Вопрос задан
  • 4196 просмотров
Подписаться 1 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 4
@mayorovp
Откройте инструменты разработчика в браузере Chrome или их аналог в другом браузере, и посмотрите, отправляется ли вообще второй запрос. И если отправляется - то в каком он состоянии.

Если запрос не отправляется - значит, проблема на стороне клиента.
Если запрос в состоянии Stalled (это такое состояние в хроме, не знаю как оно в других браузерах называется) - значит, вы уперлись в число запросов на домен.
Если запрос в состоянии SendingRequest - вы уперлись в число одновременных процессов на сервере.
Если запрос в состоянии Waiting - вероятно, вы уперлись в блокировку сессии. Хотя возможен и вариант с числом процессов или с любой другой блокировкой.
Ответ написан
Комментировать
@bx-coder
За год ответ не выбран. Для тех кто наткнется на топик: возможно идет блокировка файла сессии при первом запросе и последующие запросы становятся в очередь. Здесь описаны методы решения .
Ответ написан
Комментировать
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
последовательная биндовка ").factory" заставляет ждать 1-го ответа....
Ответ написан
@Demetros
Вы уверены, что дело именно в клиентской части?
Может у вас на сервере работает всего один процесс, который не может обработать более одного запроса одновременно?
Если во время этой долгого запроса руками подергать запрос прогресса - он будет отрабатывать сразу?
Ответ написан
Ваш ответ на вопрос

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

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