0

I have encountered an error running angularjs calling a rest service. Details below.

Here is my app.js code:

angular.module('myApp', []);

angular.module('myApp').factory('weatherService',function($http){
    return {
        getWeather:function(city,country){
            var query = 'city=' + city + '&country=' + country;
            return $http.get('http://api.openweathermap.org/data/2.5/weather',{
                params: {
                    q:query
                }
            }).then(function(response){
                return response.data.weather[0].description;
            });
        }
    }
});

angular.module('myApp').controller('WeatherController',
    function($scope,weatherService){
        $scope.getWeather=function(city,country){
            $scope.WeatherDescription = "Fetching...";
            weatherService.getWeather(city,country).then(function(data){
                $scope.weatherDescription = data;
            }, function(data){
                $scope.weatherDescription = "Could not obtain data";
            });
        }
});

html code:

<html ng-app="myApp">
    <script src="../js/angular/angular.js" ></script>
    <script src="../js/app.js" ></script>
        <body ng-controller="WeatherController">
            {{getWeather('chicago','usa')}}
        </body>
</html>

I get a blank response in the page. When I open the console, I get this error:

Watchers fired in the last 5 iterations: []
http://errors.angularjs.org/1.3.13/$rootScope/infdig?p0=10&p1=%5B%5D
    at angular.js:63
    at Scope.$digest (angular.js:14281)
    at Scope.$apply (angular.js:14506)
    at done (angular.js:9659)
    at completeRequest (angular.js:9849)
    at XMLHttpRequest.requestLoaded (angular.js:9790)
(anonymous) @ angular.js:11607
(anonymous) @ angular.js:8557
$apply @ angular.js:14508
done @ angular.js:9659
completeRequest @ angular.js:9849
requestLoaded @ angular.js:9790
angular.js:63 Uncaught Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!

what could possible be wrong? Anyone can help? I am using version 1.6.1 by the way

Thank you.

6
  • I think it is because you called the getWeather('chicago','usa') function from interpolation. Once try calling it in controller and show the result in view(HTML). Commented Jan 4, 2017 at 5:05
  • what do you mean calling it from interpolation? Commented Jan 4, 2017 at 5:07
  • Calling from view is not problem, It will work, the problem is something else Commented Jan 4, 2017 at 5:07
  • Interpolation is always looking for value. But, it is not having data as it returns promise. So, digest cycle runs for many times to have some value. When it reaches many cycles, it throws error I think. Commented Jan 4, 2017 at 5:09
  • i changed body content to {{weatherDescription}} and error was eliminated. but i am getting a blank response. Shouldnt it be 'could not obtain data' if there was an error in the called rest service? Commented Jan 4, 2017 at 5:09

2 Answers 2

1

This is related to how angular $digest cycles work, and how expressions are evaluated.

You have an expression {{getWeather('chicago','usa')}} in your HTML. Whenever a $digest cycle occurs, this expression will be evaluated, and the function will be called.

The function is setting a value $scope.WeatherDescription = "Fetching...";, then calling an async function. The change in $scope.WeatherDescription is then causing a new $digest iteration. The new $digest iteration is encountering the expression, and firing off the function (again). Even if the data comes back from the promise, it's also going to cause a property on $scope to change, which is going to cause (another) $digest, causing (another!) call to the function... This will essentially happen infinitely, which is why angular automatically preempts the processing after 10 cycles.

It is sometimes ok to trigger a function call in an expression, but in order for that to work, the function call needs to return a value, and also needs to not trigger the change to another property on $scope unrelated to the expression.

In your case, instead of using $scope.WeatherDescription, you would want to return the promise from your service.

Sign up to request clarification or add additional context in comments.

7 Comments

i changed body content to {{weatherDescription}} and error was eliminated. but i am getting a blank response. Shouldnt it be 'could not obtain data' if there was an error in the called rest service? –
no, because if you change the expression to the output of the function, you still need to trigger the function somewhere. If you called the function from your controller, then that could work.... otherwise, {{weatherDescription}} will always be empty, since the function (and the $http request) never happen.
i returned the weather description and changed the html back to {{getWeather('chicago','usa')}} and the digest error came back
are you still changing $scope.WeatherDescription?
weatherService.getWeather(city,country).then(function(data){ var weatherDescription = data; return weatherDescription; }
|
0

You can check if a $digest is already in progress by checking $scope.$$phase.

weatherService.getWeather(city,country).then(function(data){
              if(!$scope.$$phase) {
                $scope.weatherDescription = data;
              }
           }, function(data){
              if(!$scope.$$phase) {
                $scope.weatherDescription = "Could not obtain data";
              } 
         });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.