AngularJS - Infinite loop due to promise object

I'm new to AngularJS, so it might actually point to some core concept that I don't understand yet. I am trying to process "remote data" like local data using objects $q

and promise

. Until the deleted data is retrieved, the object promise

will not be resolved, but once it is resolved I want all dependent data bindings in the view to be updated. However, the following approach results in an infinite loop in which it remote_total

is called many times, even with the previous call, it remote_total

resulted in a resolved promise subject.

Here is what my look looks like

<div ng-controller="MyController">
  {{ remote_total() }}
</div>

      

Here's the relevant snippet from the controller:

function MyController($scope, $q, $http) {
  $scope.remote_total = function() {
    var def = $q.defer();
    $http.get('/my/remote/service.json').success(function(data) {
      def.resolve(data);
    });
    return def.promise;
  }
}

      

Firstly, it would be great if someone could explain to me why exactly this ends up in an infinite loop. Second, what's the best way to achieve what I am trying to do?

+3


source to share


2 answers


NOTE. See the UPDATE below for Angular 1.2+

The actually interesting thing with AngularJS promises (which $q

ensures) is that they are recognized by AngularJS. And one more thing, that they are chains!

So, in your code, you can simply

$scope.remote_total = $http.get('/my/remote/service.json').then(function(data) {
  return data;
});

      

and when viewed just <div>{{remote total}}</div>

(note: not a function, just a value).



And AngularJS will automatically recognize that promise, resolve the $ http.get promise, and then connect to your function and add the final value to the template.

What all:)

UPDATE: Automatic de-packaging of promises is disabled by default in AngularJS 1.2 and will be removed completely in 1.3.

Code that will work:

$http.get('/my/remote/service.json').then(function(data) {
  $scope.remote_total = data;
});

      

+5


source


Angular does a dirty check to achieve two way binding. In each loop, it stores the previous value of the viewed object and compares it to the new value. If this property is a function, it is called and the result is compared.

You have put a function to be watched and in each loop the function will be called, hence the result will be an http request.

What you want to do is create your promise yourself and attach the promise to it for viewing (or displaying).

Also, the $ http service already returns a promise, you don't need to create another promise.



function MyController($scope, $q, $http) {
  $scope.getRemoteTotal = function() {
    var def = $http.get('/my/remote/service.json').success(function() {
      $scope.remoteTotal = data;
    });
  }
  $scope.getRemoteTotal();
}

      

...

<div ng-controller="MyController">
  {{ remoteTotal }}
</div>

      

+3


source







All Articles