Angular.js pass data from async service to scope

前端 未结 4 1196
予麋鹿
予麋鹿 2020-12-13 11:20

I have a service like

app.factory(\'geolocation\', function ($rootScope, cordovaReady) {
    return {
        getCurrentPosition: cordovaReady(function (onSu         


        
相关标签:
4条回答
  • 2020-12-13 11:49

    Correct me if I'm wrong, but the presented solution won't work completely anymore, since newer Angular versions (>1.2!?) do no longer unwrap $q promises automatically.

    Thus:

    $scope.city = geolocation.getCurrentCity();
    

    will always be a promise. So you will always have to use:

    geolocation.getCurrentCity().then(function(city) {
        $scope.city = city;
    }
    
    0 讨论(0)
  • 2020-12-13 11:53

    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
       });     
    };
    
    0 讨论(0)
  • 2020-12-13 11:54

    Just call your onSuccess method in the service instead of handling the result there.

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

    And in your controller, parse the results and assign the city:

    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;
       });
    };
    
    0 讨论(0)
  • 2020-12-13 12:05

    Try this

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

    Sometimes, the watcher is not always called when instanciating the controller, by forcing a digest event, if the scope is not in phase, you can go to where you want to go, I believe. Let me know if I didn't understand your question.

    Oh and I don't know if i read the code properrly but it seems that you're not calling the onSuccess callback in your function: replace your getCurrentCity function by this:

    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);
                    }
                });
            });
        }
    
    0 讨论(0)
提交回复
热议问题