等待事件发生在角度JS的服务器端

时间:2016-12-05 22:45:25

标签: angularjs

我是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);
});

2 个答案:

答案 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>