我有以下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>
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();
答案 0 :(得分:3)
正如里卡多所说,一种选择是通过调用处理的同一频道反馈状态消息 - 这在技术上可能超过AJAX请求,但需要对网络服务器和任何中间组件进行大量修改。将内容刷新回Javascript,以及javascript中的复杂性来处理部分响应。这是websockets旨在解决的问题。通过HTTP请求处理long running process是不好的做法。
对此方法的进一步考虑是HTTP及其基础结构是围绕服务器及时响应请求的概念而设计的。
如果你没有沿着这条路走下去,那么你需要通过一个不同的渠道提供数据 - 显而易见的解决方案是一个AJAX网络服务,它将迅速响应当前状态。
但由于它与调用分离,因此需要一种机制来引用正在监视的特定进程。如果您已经有会话,那么您可以使用会话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);
}
和pollStatus.php:
<?php
print json_encode(
array('status'
=>file_get_contents('/tmp/' . basename($_GET['taskKey']))
));
答案 1 :(得分:0)
如果您不使用Websockets(或某种类型的服务器推送),您将不得不诉诸long-polling。
我的建议是你的控制器中的以下内容:
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);
});
}
然后,在服务器端,您必须将进度存储在数据库中(或者您可能具有的任何等效内容),以便轮询操作进行检查。在sleep
之后的每个进度步骤,您都必须更新此状态。
希望这些信息可以帮助您入门:)