0

我正在构建一个天气应用程序,我首先必须获取用户的位置,然后发出获取天气的请求。

所以我有一个GeolocationService和一个WeatherService。我WeatherService目前正在致电Geolocation服务。如何在发出 HTTP 请求之前WeatherService等待它得到结果?GeolocationService

  app.factory('GeolocationService',function($q,$window,$rootScope){
        返回 {
            getLatLon:函数(){
                var deferred = $q.defer();
                如果(!window.navigator){
                    $rootScope.$apply(function(){
                        deferred.reject(new Error("地理位置不可用"));
                    });
                } 别的 {
                    $window.navigator.geolocation.getCurrentPosition(函数(位置){
                        $rootScope.$apply(function(){
                            deferred.resolve(位置);
                        });
                    },函数(错误){
                        $rootScope.$apply(function(){
                            deferred.reject(错误);
                        });
                    });
                }

                返回 deferred.promise;
            }
        };
    });

    app.factory("WeatherService", function ($q,$http,$rootScope, GeolocationService) {
        返回 {
            获取天气:函数(){
                var 天气;
                var loc = new GeolocationService.getLatLon();
                var lat= loc.lat || 37.4568202221774,
                lon= loc.lon || -122.201366838789;
                变量单位 = '';
                var url = 'http://api.openweathermap.org/data/2.5/forecast/daily?lat='+lat+'&lon='+lon+'&units='+units+'&callback=JSON_CALLBACK';
                $http.jsonp(网址)
                    .成功(功能(数据){
                        天气=数据;
                        返回天气;
                    })
                    .错误(函数(错误){
                        天气=错误;
                        返回错误;
                    });
            }

        };
    });

4

2 回答 2

2

你只需要在你的服务中使用承诺,然后链接承诺。对于示例,我有一个 user.company_id 的用户,如果我想获得公司的名称,我必须等待用户加载。和你的情况一样。

这是我的服务:

    angular.module('UserService', []) 
.factory('UserService', function($q , $http, $rootScope,$timeout) {
var currentUserPromise = null;
var currentCompanyPromise = null;
return {
    getCurrentUser: function() {
        if (currentUserPromise === null) {
            var config = {};
            config.cache = true;
            config.method = "GET"; 
            config.url = "users/get_current_user";
            currentUserPromise = $http(config)
                .then(function(response) {
                    if (typeof response.data === 'object') {
                        return response.data.user;
                    } else {
                        // invalid response
                        return $q.reject(response.data);
                    }  
                }, function(response) {
                    // something went wrong
                    return $q.reject(response.data);
                });
        }
        return currentUserPromise;
    },

    getCurrentCompany: function(company_id) {
        if (currentCompanyPromise === null){
            var config = {};
            var company = {};
            company.id = company_id; 
            config.cache = true;
            config.method = "GET"; 
            config.url = "/companies/show";
            config.params = company;
            currentCompanyPromise = $http(config)
                .then(function(response) {
                    if (typeof response.data === 'object') {
                        return response.data.company;
                    } else {
                        // invalid response
                        return $q.reject(response.data);
                    }

                }, function(response) {
                    // something went wrong
                    return $q.reject(response.data);
                });
            }
            return currentCompanyPromise;

        }
    };     
});

在我的控制器中,我这样使用:

控制器 :

var promiseCurrentUser = UserService.getCurrentUser();
promiseCurrentUser.then(function(user) {
    $scope.currentUser = user;
    UserService.getCurrentCompany(user.company_id).then(function(company){
        $scope.companyName = company.name;
    });
});

承诺的酷之处在于它是一次解决。

我希望这能帮到您。

于 2013-11-12T20:18:46.263 回答
1

GeolocationService的功能getLatLon是返回一个承诺。无需使用new操作员调用它。

您的getWeather函数应该类似于以下内容:

app.factory("WeatherService", function ($q,$http,$rootScope, GeolocationService) {
    return {
        getWeather: function(){
            var weather;
            return GeolocationService.getLatLon().then(
                function (loc) {
                    var  lat= loc.lat || 37.4568202221774, 
                    lon= loc.lon || -122.201366838789 ;
                    var units = '';
                    var url = 'http://api.openweathermap.org/data/2.5/forecast/daily?lat='+lat+'&lon='+lon+'&units='+units+'&callback=JSON_CALLBACK';
                    return $http.jsonp(url)
                        .success(function(data) {
                            weather=data;
                            return weather;
                        })
                        .error(function(err){
                            weather=err;
                            return err;
                        });
            });
        }
    }
}

在这里,我们首先调用GeolocationService.getLatLon()来获得一个promise。然后我们将我们的处理链作为一个链链接到它。成功功能将使position您在这里解决它deferred.resolve(position);

此外,您不需要将resolveand包装reject$apply. 因此,您GeoLocationService可以简化为:

            if(!window.navigator){
                deferred.reject(new Error("Geolocation not available"));
            } else {
                $window.navigator.geolocation.getCurrentPosition(function(position){
                        deferred.resolve(position);
                }, function(error){
                        deferred.reject(error);
                });
            }
于 2013-11-12T20:19:50.467 回答