我是angularJS的新手。我需要开发一个页面,其中angular JS等待事件发生在服务器端,因此有角度的JS应该每2秒使用$ http调用继续检查服务器。一旦该事件完成,Angular不应再次调用任何$ http调用服务器。
我尝试了不同的方法,但它给了我一个错误,就像#34; Watchers在最后5次迭代中被解雇:[]"
请让我知道怎么做。
以下是我的代码
HTML
<div ng-controller="myController">
<div id="divOnTop" ng-show="!isEventDone()">
<div class="render"></div>
</div>
</div>
Angular JS
var ngApp = angular.module("ngApp",[]);
ngApp.controller('myController', function ($scope, $http) {
$scope.ready = false;
$scope.isEventDone = function () {
$scope.ready = $scope.getData();
return $scope.ready;
};
$scope.getData = function () {
if (! $scope.ready) {
$http.get("/EventManager/IsEventDone")
.then(function (response) {
$scope.ready = Boolean(response.data);
});
}
};
setInterval($scope.isPageReady, 5000);
});
答案 0 :(得分:1)
这里有一些事情。
我不相信接受的答案实际上有效,也解决了最初的问题。所以,我会在这里分享我的2美分。
$scope.ready = $scope.getData();
每次都会将$scope.ready
设置为undefined
,因为此方法不会返回任何内容。因此,ng-show="!isEventDone()"
将始终显示DOM。
您应该使用角度$interval代替setInterval
进行角度短轮询。
另外,我重构了一些冗余。
var ngApp = angular.module("ngApp",[]);
ngApp.controller('myController', function ($scope, $http, $interval) {
var intervalPromise = $interval($scope.getData, 5000);
$scope.getData = function () {
if (! $scope.isEventDone) {
$http
.get("/EventManager/IsEventDone")
.then(function (response) {
$scope.isEventDone = Boolean(response.data);
if($scope.isEventDone) {
$interval.cancel(intervalPromise);
}
});
}
else {
$interval.cancel(intervalPromise);
}
};
});
这应该可以解决您的初始问题。但是,有一种情况是您的服务器可能处于高负载状态并需要3秒钟才能响应。在这种情况下,您每2秒调用一次服务器,因为您在上一个请求开始后等待5秒钟而不是在上一个请求结束后等待。
比这更好的解决方案是使用像async
这样的模块,它可以轻松处理异步方法。结合$timeout:
var ngApp = angular.module("ngApp",[]);
ngApp.controller('myController', function ($scope, $http, $timeout) {
var getData = function(cb){
if(!$scope.isEventDone) return cb();
$http.get("/EventManager/IsEventDone")
.then(function (response) {
$scope.isEventDone = Boolean(response.data);
cb();
});
};
// do during will run getData at least once
async.doDuring(getData, function test(err, cb) {
// asynchronous test method to see if loop should still occur
// call callback 5 seconds after getData has responded
// instead of counting 5 seconds after getData initiated the request
$timeout(function(){
cb(null, !$scope.isEventDone);
// if second param is true, call `getData()` again otherwise, end the loop
}, 5000);
}, function(err) {
console.log(err);
// if you're here, either error has occurred or
// the loop has ended with `$scope.isEventDone = true`
});
});
这将在请求结束后调用超时。
如果您拥有对服务器的控制权,更好的选择是使用websocket来启用长轮询(服务器通知客户端而不是客户端频繁请求),这不会增加显着的负载服务器随着客户的增长而增长。
我希望这会有所帮助
答案 1 :(得分:0)
在您的示例中,$ scope.pageIsReady不存在。你可以做的是将$ timeout服务注入你的控制器并将你的http调用包装在其中:
var timeoutInstance = $timeout(function(){
$http.get("/EventManager/IsEventDone")
.then(function (response) {
$scope.ready = Boolean(response.data);
if($scope.ready){
$timeout.cancel(timeoutInstance);
else
$scope.getData();
}
});
},5000);
取消将停止调用超时。我没有对此进行过测试,但它应该是这样的。
还不确定你使用的是什么类型的后端,但如果它是.net,你可以查看使用套接字的SignalR,这样服务器端就会在准备就绪时告诉前端,因此你不再需要使用轮询。 / p>