11

我有这样的服务

app.factory('geolocation', function ($rootScope, cordovaReady) {
    return {
        getCurrentPosition: cordovaReady(function (onSuccess, onError, options) {

            navigator.geolocation.getCurrentPosition(function () {
                var that = this,
                    args = arguments;

                if (onSuccess) {
                    $rootScope.$apply(function () {
                        onSuccess.apply(that, args);
                    });
                }
            }, function () {
                var that = this,
                    args = arguments;
                if (onError) {
                    $rootScope.$apply(function () {
                        onError.apply(that, args);
                    });
                }
            }, options);
        }),
        getCurrentCity: function (onSuccess, onError) {
            this.getCurrentPosition(function (position) {
                var geocoder = new google.maps.Geocoder();
                geocoder.geocode(options,function (results, status) {
                    var city = address_component.long_name;
                });
            });
        }
    }
});

我想从控制器做类似的事情

function MainCtrl($scope, geolocation) {
   geolocation.getCurrentCity(function(city){
       $scope.city = city;
   });
};

getCurrentPosition 工作正常,城市也确定了,但是我不知道如何在控制器中访问城市。

怎么了?当调用 getCurrentCity 时,它调用 getCurrentPosition 来确定 gps 坐标。这个坐标作为参数传递给 onSuccess 方法对吗?所以这和我想在 getCurrentCity 方法中做的完全一样,但我不知道怎么做。异步地理编码器检索到城市,我想将新数据应用于 onSuccess 方法。

有任何想法吗?

4

4 回答 4

29

You are dealing with callbacks and asynchronous request. So you should use $q service. Just inject it in your service with $rootScope and cordovaReady dependency. And add the promises to your function like this

getCurrentCity: function () {
    var deferred = $q.defer(); 
    this.getCurrentPosition(function (position) {
      var geocoder = new google.maps.Geocoder();
      geocoder.geocode(options,function (results, status) {
        var city = address_component.long_name;
        $rootScope.$apply(function(){
          deferred.resolve(city);
        });
      });
    });
    return deferred.promise;
}

And in your controller, do the following to handle the promise.

function MainCtrl($scope, geolocation) {
   geolocation.getCurrentCity().then(function(result) {  //result === city
     $scope.city = result;
     //do whatever you want. This will be executed once city value is available
   });     
};
于 2013-07-23T23:59:55.207 回答
5

尝试这个

function MainCtrl($scope, geolocation) {
   $scope.city = null;
   geolocation.getCurrentCity(function(city){
       $scope.city = city;
       if(!$scope.$$phase) {
            $scope.$digest($scope);
        }
   });
};

有时,在实例化控制器时并不总是调用观察者,通过强制摘要事件,如果范围不同步,我相信你可以去你想去的地方。如果我不明白你的问题,请告诉我。

哦,我不知道我是否正确阅读了代码,但似乎你没有在你的函数中调用 onSuccess 回调:用这个替换你的 getCurrentCity 函数:

getCurrentCity: function (onSuccess, onError) {
        this.getCurrentPosition(function (position) {
            var geocoder = new google.maps.Geocoder();
            geocoder.geocode(options,function (results, status) {
                var city = address_component.long_name;
                if(typeof onSuccess === 'function') {
                     onSuccess(city);
                }
            });
        });
    }
于 2013-07-24T09:32:42.923 回答
4

只需在服务中调用您的 onSuccess 方法,而不是在那里处理结果。

getCurrentCity: function (onSuccess, onError) {
    this.getCurrentPosition(function (position) {
        var geocoder = new google.maps.Geocoder();
        geocoder.geocode(options, onSuccess);
    });
}

在您的控制器中,解析结果并分配城市:

function MainCtrl($scope, geolocation) {
   geolocation.getCurrentCity(function(results, status){
       // Parse results for the city - not sure what that object looks like
       $scope.city = results.city;
   });
};
于 2013-07-21T16:38:35.960 回答
3

如果我错了,请纠正我,但所提出的解决方案将不再完全有效,因为较新的 Angular 版本(> 1.2!?)不再自动解开 $q 承诺。

因此:

$scope.city = geolocation.getCurrentCity();

将永远是一个承诺。因此,您将始终必须使用:

geolocation.getCurrentCity().then(function(city) {
    $scope.city = city;
}
于 2014-01-10T14:24:16.477 回答