Tim Tim - 4 months ago 19
AngularJS Question

Can't access returned object - resource service

This is my first Angular app so I'm sure there's something obvious I'm doing wrong, but I've Googled and searched this site without any luck.

I'm using the $resource service to make an AJAX call to get some JSON from a weather API. The function below retrieves it (via the weatherService's function) and I'm able to successfully log the returned object to the screen (console screenshot). When I try to access any of the object's properties (ex. info.cnt), logging it returns undefined. Can't figure out why this is. Any help would be much appreciated.

$scope.submit = function() {
var info = weatherService.getForecast(weatherService.city);
console.log(info);
}


My custom weather service:

weather.service('weatherService', function($resource){

this.city = 'Chicago, IL';

this.getForecast = function(location) {

this.weatherAPI = $resource("http://api.openweathermap.org/data/2.5/forecast/daily", { callback: "JSON_CALLBACK" }, { get: { method: "JSONP" }});

this.weatherResult = this.weatherAPI.get({ q: this.city, cnt: 5, appid: 'e92f550a676a12835520519a5a2aef4b' });

return this.weatherResult;
}

});

Answer

Your get call will be executed async. So, your service should be like:

weather.service('weatherService', function($resource){

    this.city = 'Chicago, IL';

    this.getForecast = function(location) {

        this.weatherAPI = $resource("http://api.openweathermap.org/data/2.5/forecast/daily", { callback: "JSON_CALLBACK" }, { get: { method: "JSONP" }});

        return this.weatherAPI.get({ q: this.city, cnt: 5, appid: 'e92f550a676a12835520519a5a2aef4b' });

    }

});

and you should consume like:

$scope.submit = function() {
    weatherService.getForecast(weatherService.city, function(response) { 
        //DO SOMETHING WITH THE RETURN 
    });
};

You can see that we are passing a callback, that will be called when the HTTP request is completed.

If you want to be more advance, you can, and should, use promises. It would became:

$scope.submit = function() {
   weatherService.getForecast(weatherService.city).$promise.then(function(response){
        //SUCCESS
    }).catch(function(error){
        //ERROR
    });
};

Take a look at the docs, to see some more awesome functionalities.

So, why you still see same data in the screen:

The thing is that the $resource service mimics a sync operation. Given the data-binding of angular, if you tied your return to the $scope, the response eventually will be completed, and during the $digest cycle, the framework will revisit your variable and see that it has some data. But, like I said, it is due to the data-binding, you can't, as you saw, access immediately your data.

Comments