1

so I finally got my app working to where it gets the right URL for the JSON request. However now I can't get it work with that URL.

I understand that the service is returning the promise from the Google Maps API, which I probably shouldn't do but if I leave it out I get a "Weather.getWeather is undefined" error. I don't know why.

How can I get this to work correctly. Thanks for any help.

weatherService.getWeather = function(city)  {


        var coordsUrl = 'https://maps.googleapis.com/maps/api/geocode/json?address=' + city;


        return $http.get(coordsUrl)
            .success(function(data) {
                var coords = data.results[0].geometry.location.lat + ',' + data.results[0].geometry.location.lng;

            return getWeatherData(coords);  

        }); 

function getWeatherData(coords)  {
            var deferred = $q.defer(),
            apiKey = 'cbbdddc644184a1d20ffc4a0e439650d',
            weatherUrl = 'https://api.forecast.io/forecast/' + apiKey + '/' + coords + '?callback=JSON_CALLBACK';


            $http.jsonp(weatherUrl)
                .success(function(data) {

                    deferred.resolve(data);

                }).error(function(err) {

                    deferred.reject(err);

                });

            console.log(weatherUrl);

            return deferred.promise;
        }        

    };

Controller:

vm.fetchWeather = function(city) {

    Weather.getWeather(city)
        .then(function(data) {
            console.log(data);
            vm.place = data;
    });
};
1
  • 1
    $http methods return a promise, wrapping them in a $q.defer() is an anti-pattern. Commented Sep 6, 2015 at 20:48

1 Answer 1

5

You shouldn't use .success in your getWeather service function that wouldn't allow you return any sort of data. Because callback function's are not capable of returning anything Read Here about callback & promise. So you should go for the promise recipe to dealing with asynchronous request, basically you can return data from the promise function to consumer function which calls that function. Actually it does call the consumer .then function, when ajax completed.

You need to simply use .then function in your getWeather function, then on resolve of that async call it will call the getWeatherData function which again will again returns a promise. So when it gets resolved it call .then function of getWeatherData when it returns data from it, at that time Weather.getWeather(city)'s .then function will get call. This whole thing is nothing but you implemented in promise chain. One function wait for other's, once the underlying promise gets resolved, it call its .then function.

Read here about Promise

Code

return $http.get(coordsUrl)
 .then(function(resp) {
    var data = resp.data
    var coords = data.results[0].geometry.location.lat + ',' + data.results[0].geometry.location.lng;
    return getWeatherData(coords);  
}); 

Also there is not need of creating an extra promise inside getWeatherData function as you can utilize the promise of $http call there.

Code

function getWeatherData(coords)  {
    var apiKey = 'cbbdddc644184a1d20ffc4a0e439650d',
    weatherUrl = 'https://api.forecast.io/forecast/' + apiKey + '/' + coords + '?callback=JSON_CALLBACK';

    return $http.jsonp(weatherUrl)
    .then(function(resp) {
       var data = resp.data;
       //you could play with data here before returning it.
       return data;
    },function(error) {
       return error;
    });
}

Edit by Roamer-1888

Alternatively, modify getWeatherData() to accept data and to calculate coords for itself. Then, the flow control statement will simplify to return $http.get(coordsUrl).then(getWeatherData);.

weatherService.getWeather = function(city) {
    var coordsUrl = 'https://maps.googleapis.com/maps/api/geocode/json?address=' + city;
    function getWeatherData(data) {
        var apiKey = 'cbbdddc644184a1d20ffc4a0e439650d',
            coords = data.results[0].geometry.location.lat + ',' + data.results[0].geometry.location.lng,
            weatherUrl = 'https://api.forecast.io/forecast/' + apiKey + '/' + coords + '?callback=JSON_CALLBACK';
        return $http.jsonp(weatherUrl);
    }
    return $http.get(coordsUrl).then(getWeatherData);
};
Sign up to request clarification or add additional context in comments.

12 Comments

Hey Pankaj, I'm still not fully getting it. Could you explain in a little more detail. Thanks!
@DevonAero sure..give me 5 minutes please
Thanks for the explanation @Pankaj! However, now my controller is returning 'undefined' and not the data Object.
@DevonAero try updated.Actully i missed to use .then in $http.jsonp(weatherUrl) .I'm updating my answer with detailed..
Opps, nevermind. I missed the return statement in your example. But, figured it out myself haha. Thanks so much for you help. So I don't need to ever use the $q object or the success callback?
|

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.