F
F
faragly2015-02-01 12:03:49
JavaScript
faragly, 2015-02-01 12:03:49

2 angular AJAX requests. How to get the response to the second request while the first one is running?

Hello dear developers! Please help me figure it out. There is a php function that works for a long time (5-10 seconds), and the recording of intermediate data is triggered in this function step by step (using the Flintstone.php file database). If you run the function, you can see how the data changes when the database file is open. So, AngularJS works on the client side, 2 ajax requests are created - the first one launches a large function that will take a long time and write intermediate data to the database, the second request is sent after 1 second and runs in a loop until the script is completed.
The HTML is this (at startup, the request is sent):

<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 code is below:
'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'
    }
  });
});

The PHP code has been simplified as much as possible to make it clearer:
<?
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();
?>


In general, the response to an intermediate request does not come until the first request is completed. Help me to understand.

Answer the question

In order to leave comments, you need to log in

4 answer(s)
M
mayorovp, 2015-02-02
@mayorovp

Open the developer tools in Chrome browser or equivalent in another browser and see if the second request is sent at all. And if sent - then in what condition is it.
If the request is not sent, then the problem is on the client side.
If the request is in the Stalled state (this is such a state in chrome, I don’t know what it is called in other browsers) - it means that you have hit the number of requests for the domain.
If the request is in the SendingRequest state, you hit the number of simultaneous processes on the server.
If the request is in the Waiting state, you probably hit a session lock. Although the option with the number of processes or with any other lock is also possible.

B
bx-coder, 2016-09-14
@bx-coder

No answer has been selected for the year. For those who stumble upon the topic: it is possible that the session file is being blocked on the first request and subsequent requests are queued. Solution methods are described here.

X
xmoonlight, 2015-02-01
@xmoonlight

sequential binding ").factory" makes you wait for the 1st response....

D
Dmitry Dedukhin, 2015-02-01
@Demetros

Are you sure it's in the client side?
Maybe you have only one process running on the server that cannot process more than one request at the same time?
If, during this long request, you pull the progress request with your hands, will it work right away?

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question