1

In an AngularJS project, I'm able to display a list of events with a call to $scope.loadEvent, but then not able to update the view when polling the server using $http and $timeout. I can see that the correct $http calls and responses are being made/received.

A condensed version of the controller:

function EventsCtrl ($scope, $http, $timeout) {

  $scope.myEvents = new Array();
  var newMyEvents = new Array();

  $scope.loadEvent = function(eventId) {
    $http.get('http...').success(function(result) {
        $scope.myEvents.push(result.data);
    });
  }

  $scope.polling = function () {
      var poller = function() {
          newMyEvents = [];
          for(var i=0; i< $scope.myEvents.length; i++) {
              $http.get('http...').success(function(result) {
                  newMyEvents.push(result.data);
              });
          }
          $timeout(poller, 2000);
      }
      $scope.myEvents = newMyEvents;
      poller();
  }
}

and the view:

<div ng-controller="EventsCtrl" ng-init="polling()">

I've tried $scope.$apply(), which returns Error: $apply already in progress as it seems $http is already "inside" Angular.

Any and all thoughts appreciated. Thanks.

ozandlb
  • 1,024
  • 2
  • 10
  • 23
  • 1
    You probably have to use [`$scope.apply()`](https://github.com/angular/angular.js/wiki/When-to-use-$scope.$apply()) – NilsH May 17 '13 at 07:48
  • Tried before and got "Error: $apply already in progress", maybe because I'm already using $http. – ozandlb May 17 '13 at 08:28
  • Are you using the 1.1.X version of angular? I've experienced some issues with timeouts/intervals not firing. Try the 1.0.X release series. – nathasm Jun 27 '13 at 17:27

1 Answers1

0

In some cases you will need to use $scope.$apply();

Try performing:

$scope.$apply(function() {
  $scope.myEvents = newMyEvents;
}

EDIT I misunderstood what's happening completely. The problem is that you are firing all of those queries asynchronously, so you have no way of knowing when each of them finishes. Also, $timeout automatically executes $scope.$apply for you. If you want to be in control of when to actually $apply you can use setTimeout() instead.

Perhaps you could perform $scope.myEvents = newMyEvents within the callback of the last $http request (you don't have 100% guarantee it would actually get the data last). Best way would be executing one call to the backend that fetches all of the resource for you so that you can update the variable in the .success function directly. (if that is achievable)

More about $apply and how to prevent the error

Community
  • 1
  • 1
Bogdan Rybak
  • 2,107
  • 1
  • 19
  • 22
  • As commented above, got `Error: $apply already in progress`. Also, am not able to send and receive the polling messages by shifting the `$timeout` and `$scope.myEvents` assignment. The code posted in the original question is able to achieve the correct messages and frequency, though it does not result in an updated view. – ozandlb May 17 '13 at 08:34
  • Is it an option to just update $scope.myEvents upon $http success? – Bogdan Rybak May 17 '13 at 19:05