如何让PHP更新javascript的冗长进程状态?

如何让PHP更新javascript的冗长进程状态?,javascript,php,angularjs,Javascript,Php,Angularjs,我有下面的Angular站点,它显示Angular可以在PHP通过AJAX在后台执行某些进程时更新页面 但是,我现在如何才能让我的PHP进程,例如for循环传回$x的值,以便在其递增时显示$x的后续值 index.php <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>ajaxtest</title>

我有下面的Angular站点,它显示Angular可以在PHP通过AJAX在后台执行某些进程时更新页面

但是,我现在如何才能让我的PHP进程,例如
for
循环传回
$x
的值,以便在其递增时显示
$x
的后续值

index.php

<!doctype html>
<html lang="en">
    <head>
      <meta charset="utf-8">
      <title>ajaxtest</title>
      <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
    </head>
    <body ng-app="mainApp">
        <div ng-controller="mainController">
            <div>Angular is counting: {{counter}}</div>
            <button ng-click="processFiles()">processFiles</button>
            <div>{{message}}</div>
        </div>

        <script>
        var mainApp = angular.module('mainApp',[]);
        function mainController($scope, $interval, $http) {

            var theTimer = $interval(function () {
                $scope.counter++;
            }, 1000);           

            $scope.counter = 0;
            $scope.message = 'click the button to have PHP do something in the background while Angular should continue to count';

            $scope.processFiles = function() {
                $scope.message = 'processing...';
                $http.get('http://localhost/webs/ajaxtest/data.php', {
                    params: {
                        taskIdCode: 'getLoadingStatus'
                    }
                }).success(function (data) {
                    $scope.message = data['status'];
                }); 
            }
        }
        </script>
    </body>
</html>
        $taskIdCode = filter_input(INPUT_GET, 'taskIdCode', FILTER_UNSAFE_RAW);
        $methodName = 'task_' . $taskIdCode;
        $this->$methodName();
    }
    public function task_getLoadingStatus() {
        for($x = 1; $x <= 4; $x++) {
            sleep(1);
        }
        $data['status'] = 'finished';
        echo json_encode($data);
    }
}
$taskRunner = new TaskRunner();

阿贾克斯试验
角度正在计数:{{counter}
处理文件
{{message}}
var mainApp=angular.module('mainApp',[]);
函数mainController($scope、$interval、$http){
var theTimer=$interval(函数(){
$scope.counter++;
}, 1000);           
$scope.counter=0;
$scope.message='单击按钮让PHP在后台执行某些操作,而Angular应继续计数';
$scope.processFiles=函数(){
$scope.message='processing…';
$http.get('http://localhost/webs/ajaxtest/data.php', {
参数:{
taskIdCode:'getLoadingStatus'
}
}).成功(功能(数据){
$scope.message=数据['status'];
}); 
}
}
data.php
        $taskIdCode = filter_input(INPUT_GET, 'taskIdCode', FILTER_UNSAFE_RAW);
        $methodName = 'task_' . $taskIdCode;
        $this->$methodName();
    }
    public function task_getLoadingStatus() {
        for($x = 1; $x <= 4; $x++) {
            sleep(1);
        }
        $data['status'] = 'finished';
        echo json_encode($data);
    }
}
$taskRunner = new TaskRunner();
$taskIdCode=filter\u input(input\u GET,'taskIdCode',filter\u UNSAFE\u RAW);
$methodName='task_u2;'$taskIdCode;
$this->$methodName();
}
公共函数任务_getLoadingStatus(){

对于($x=1;$x如果您不使用WebSocket(或某种类型的服务器推送功能),您将不得不求助于

我的建议如下:

var promise = null;
var poller = function() {
    console.log("Query the server for the amount of progress done using another $http.get");
};
在执行
$http.get
启动长操作之前的函数中:

$scope.processFiles = function() {
  $scope.message = 'processing...';

  //
  // Initialize the interval pooling operation
  //
  var promise = $interval(poller, 1000);

  $http.get('http://localhost/webs/ajaxtest/data.php', {
    params: { 
      taskIdCode: 'getLoadingStatus'
    }
  }).success(function (data) {
    //
    // Terminate the interval so it does not run forever!
    //
    $interval.cancel(promise);
    $scope.message = data['status'];
  }).error(function() {
    $interval.cancel(promise);
  }); 
}
然后,在服务器端,您必须将进度存储在数据库中(或您可能拥有的任何等效内容),以供轮询操作检查。在
睡眠之后,每个进度步骤都必须更新此状态


希望这些信息可以帮助您开始:)

正如Ricardo所说,一种选择是通过调用处理的同一通道反馈状态消息-这在技术上是可以通过AJAX请求实现的,但需要对Web服务器和任何中间组件进行大量修补,以将内容刷新回Javascript,并在Javascript中复杂地处理p艺术响应。这是WebSocket要解决的问题。通过HTTP请求处理问题不是一个好的做法

对这种方法的进一步考虑是,HTTP及其基础设施是围绕服务器对请求做出快速响应的概念设计的

如果您不走这条路线,那么您需要通过不同的渠道提供数据——显而易见的解决方案是使用AJAX Web服务,它将立即响应当前状态

但是,由于这与调用无关,因此它需要一种机制来引用正在监视的特定进程。如果您已经有会话,则可以使用会话id或会话本身作为密钥-但是,如果会话与多个这样的进程相关联,这将不起作用。此外,公开通过javascript的会话id对安全性有很大影响

或者,您可以在javascript中创建一个(希望是唯一的)键,并将该键注入到流程调用中

            var taskKeyValue=generate_unique_id();
            var keepChecking;

            // first invoke processing.....

            $scope.processFiles = function() {
            $scope.message = 'processing...';
            $http.get('http://localhost/webs/ajaxtest/data.php', {
                params: {
                    taskKey: taskKeyValue
                }
            }).success(function (data) {
                $scope.message = data['status'];
                clearInterval(keepChecking);
            }); 

            // then while this is outstanding
            var checkFiles = function() {
            $http.get('http://localhost/webs/ajaxtest/pollStatus.php', {
                params: {
                    taskKey: taskKeyValue
                }
            }).success(function (data) {
                $scope.message = data['status'];
            }); 
            keepChecking=set_interval(checkFiles, 2000);
然后在现有的php代码中

 function doing_slow_thing() {
    for($x = 1; $x <= 40; $x++) {
        file_put_contents('/tmp/' . basename($_GET['taskKey']), $x);
        sleep(1);
    }
    $data['status'] = 'finished';
    echo json_encode($data);
 }
函数做慢的事情(){

对于($x=1;$x使用WebSocket或javascript长轮询实际上我的答案与你的答案有相同的目标。轮询函数将对另一个提供当前状态的脚本执行
$http.get
。其目的不是推送部分响应或做一些不寻常的事情。我稍后将查看我的答案,看看我可以在哪里找到答案n改进:)此外,作为对您自己答案的改进,您应该使用AngularJS的
$interval
服务。尽管它主要是
setInterval
的包装器,但它更适合与AngularJS一起使用。@Piskvor:即使使用默认(阻塞)会话处理程序,您也可以关闭(并因此解锁)在代码中的任何时候都可以启动会话。请参阅会话\u写入\u关闭()