javascript Angular.js 将数据从异步服务传递到作用域

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17684153/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 09:11:46  来源:igfitidea点击:

Angular.js pass data from async service to scope

javascriptangularjs

提问by Upvote

I have a service like

我有这样的服务

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

And I want to do from a controller something like

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

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

The getCurrentPosition works fine and the city is determined too, however I don't know how to access the city in controller.

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

What happens?When getCurrentCity is called, it calles getCurrentPosition to determine the gps coords. This coords are passed as arguments to the onSuccess method right? So this is quite the same I want to do in the getCurrentCity method, but I don't know how. Ones the async geocoder retrieved the city, I want to apply the new data to the onSuccess method.

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

Any ideas?

有任何想法吗?

回答by Rishabh Singhal

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

您正在处理回调和异步请求。所以你应该使用$q服务。只需使用 $rootScope 和 cordovaReady 依赖项将其注入您的服务中即可。并像这样将承诺添加到您的功能中

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

回答by Abdoul Sy

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:

哦,我不知道我是否正确阅读了代码,但您似乎没有在函数中调用 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);
                }
            });
        });
    }

回答by Terry

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

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

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

回答by Daniel

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.

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

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