首页 文章

链接承诺,或一个承诺触发另一个承诺

提问于
浏览
0

我正在构建一个天气应用程序,我首先要获取用户位置,然后请求获取天气 .

所以我有 GeolocationServiceWeatherService . 我的 WeatherService 目前正在调用 Geolocation 服务 . 在发出HTTP请求之前,如何让 WeatherService 等到 GeolocationService 的结果?

app.factory('GeolocationService',function($q,$window,$rootScope){
        return {
            getLatLon: function(){
                var deferred = $q.defer();
                if(!window.navigator){
                    $rootScope.$apply(function(){
                        deferred.reject(new Error("Geolocation not available"));
                    });
                } else {
                    $window.navigator.geolocation.getCurrentPosition(function(position){
                        $rootScope.$apply(function(){
                            deferred.resolve(position);
                        });
                    }, function(error){
                        $rootScope.$apply(function(){
                            deferred.reject(error);
                        });
                    });
                }

                return deferred.promise;
            }
        };
    });

    app.factory("WeatherService", function ($q,$http,$rootScope, GeolocationService) {
        return {
            getWeather: function(){
                var weather;
                var loc = new GeolocationService.getLatLon(); 
                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';
                $http.jsonp(url)
                    .success(function(data) {
                        weather=data;
                        return weather;
                    })
                    .error(function(err){
                        weather=err;
                        return err;
                    });
            }

        };
    });

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;
        });
    });
    

    承诺的真正好处在于它只能解决一次 .

    我希望这能帮到您 .

  • 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() 来获得一个承诺 . 然后我们将我们的处理链接到它 . 成功函数将使用 deferred.resolve(position); 来解析 position .

    此外,您不需要在 $apply 中包装 resolvereject . 因此,您的 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);
                    });
                }
    

相关问题