简体   繁体   中英

AngularJS polling a $resource on an $interval doesn't automagically resolve the promise returned from $resource

So, the important bits: When I bind a $scope variable in my controller directly to a $resource, angular's automatic promise resolution takes over and my view gets updated as soon as data comes back from the service. However, I need to poll the server for updates on an interval. Attempting to bind to the promise returned from the $interval call is not triggering angular's automatic promise resolution and I do not know if there is something that can be done to get this $interval working against a $resource.

Angular client, ASP.NET WebApi serving JSON, Angular $resource sitting over WebApi. Inside my angular controller, if I bind a $scoped variable to my $resource promises directly, I get results; however, I need my $resources to update on an $interval and I am having problems introducing the interval.

The working, "needs manual refreshing" code (the relevant part, at least)

'use strict';
var ctrls = angular.module('MyModule',[]);
ctrls.controller('FooCtrl', ['$scope', '$location','service',
  function( $scope,$location,service)
  {
     $scope.Bars = service.Bars;
     $scope.Baz = service.Baz;
  }

var app = angular.module('MyModule.Services',['ngResource']);
app.service('service', ['$resource', function($resource)
{
  var proxy = $resource(
       'http://server/subsystem/api/Foo/:component',
        {},
        {
           Bars: {method:'GET',isArray:false,url: 'http://server/subsystem/api/Foo/Bars'
          ,Baz: {method:'GET',isArray:false,rul: 'http://server/subsystem/api/Foo/Baz'
        }
  return proxy;
}]);

blah blah blah, ng-repeat in my view bound to "bar in Bars" = data to screen.

So now, I go into my controller to implement my interval, and I can get the interval working but the promise does not resolve.

The changes inside the controller (note that I added $interval and $document to my dependency list:

var stop;
$scope.Bars = {};
$scope.Baz = service.Baz; //Note that angular resolves this promise automatically.
$scope.pollService = function(){
   if(angular.isDefined(stop))return;
   stop = $interval(function(){
     if(service){
        $scope.Bars = service.Bars;
     }
   },1000);
};
$scope.stopPolling = function(){
   if(angular.isDefined(stop)){
     $interval.cancel(stop);
     stop = undefined;
   }
};
$scope.$on('$destroy',function(){
   $scope.stopPolling();
});
$document.ready(function(){
   $scope.pollService(); //when I attempt to execute my .then() on pollService(), I get "cannot 
                         //call then on undefined"
});

Edit

Note that the problem I am having is that binding $scope.Bars directly to service.Bars triggers angular's automatic promise resolution but introducing the $interval call does not seem to be. Inspecting $scope.Bars in Chrome Dev Tools indicates that it is an unresolved promise.

I updated my sample code to match what I currently have in my debugger. I have several properties defined on my resource, and I included one that I named 'Baz'. If I assign $scope.Baz = service.Baz directly within my controller, the view binds to it when angular resolves the promise but the one on the interval never does.

You aren't returning the promise from $scope.pollService . Just add return stop; at the end of your function. Also note that the way your API is written, your function will still return undefined if stop is defined.

Therefore, it should probably look like:

$scope.pollService = function(){
   if(!angular.isDefined(stop)) {
       stop = $interval(function() {
         if(service){
            $scope.Bars = service.Bars;
         }
       }, 1000);
  }

  return stop;
};

stop is also not a very good descriptive name...

EDIT:

From my understanding after reading the docs, you should be invoking the action method on the service like $scope.Bars = service.Bars(); . This will return an object that will eventually get populated with data once the promise is resolved. However, I think you also need to be careful here, because if the interval fires faster than the promise resolving rate you might run into issues. I think that you would be better off using $timeout .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM