【问题标题】:Angular, how to know when a service is doneAngular,如何知道服务何时完成
【发布时间】:2014-01-31 08:45:16
【问题描述】:

我正在尝试在函数工作时使用 ajax 微调器,但我不知道如何在函数完成时告诉微调器隐藏。

代码是这样工作的:

  1. 单击一个按钮,将出现微调器,并触发控制器中的一个函数来更新一些数据。
  2. 该函数访问使用 $resource 更新数据的服务
  3. 无法隐藏微调器,因为我不知道该过程何时完成。

那么,我怎么知道整个事情什么时候完成,这样我就可以停止显示微调器了?

单击视图中的按钮会触发updateData()。在我的控制器中,我有:

$scope.updateData = function () {
    Data.updateData();
}

上面引用的Data服务的updateData方法是:

updateData : function() {

           API.update({
               uri     : 'updateData'
           }, {
               data     : data
           }, function(data) {
               data = data[0];
               $rootScope.$emit('Data.updateSuccess');

           }, function(err) {
               $rootScope.$emit('Data.updateError', err);
           });

该 API 来自扩展 $resource 的工厂:

.factory('API', ['$resource', function($resource){
    return $resource('/location/:uri', {}, {
        query : {
            method  : 'GET',
            isArray : true
        },
        update: {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            }
        },
        create: {
            method: 'POST',
            isArray : true,
            headers: {
                'Content-Type': 'application/json'
            }
        }
    });
}]);

}

起初我以为我可以用

在控制器中收听那些 $emits(我也尝试过 $broadcast)
    $rootScope.$on('Data.updateSuccess', $log.log('update success'));
    $rootScope.$on('Data.updateError', $log.log('update failure'));

但是当我这样做时,我每次都会得到它们。那么我需要做什么来确定在完成此更新过程时何时隐藏我的 ajax 微调器?

【问题讨论】:

  • 您可能应该返回一个 Promise 而不是仅仅调用该函数,然后向其添加一个 .then 处理程序。
  • @BenjaminGruenbaum 在我必须使用的范围内,我将如何做到这一点?

标签: javascript ajax angularjs


【解决方案1】:

您可以使用 Promise 来处理这个问题。对于一个承诺,注入 $q 服务。

您可以通过调用 $q.defer(); 来获得延期。

然后,您异步执行某些操作。在您的示例中,您将进行资源调用。当您从资源调用中取回数据时,您可以使用数据调用 deferral.resolve。那时您也可以通过 $scope 或调用服务来关闭微调器。

这是一个示例服务,它模拟了 2 秒的数据获取延迟。它向您展示了如何使用 $q 服务。想象一下调用 $resource 而不是 $timeout。

app.service("myService", function($q, $timeout) {
    var _this = this;
    this.$q = $q;
    this.$timeout = $timeout;
    var stuff = [1, 2, 3]; 
    return {
        getStuff: function() {
            var deferral = $q.defer(); 
            _this.$timeout(function() {
                deferral.resolve(stuff); 
            }, 2000);
            return deferral.promise;
        }
    };
});

接下来,这是一个使用 Promise 的控制器。请注意,它会打开微调器,然后获取数据,并在数据到达后将其关闭。同样,我是通过范围来执行此操作的,但您可以根据微调器的实现方式调用服务或发出事件。

app.controller("myController", function($scope, myService) {
    var _this = this;
    this.$scope = $scope;
    this.myService = myService;
    this.$scope.showSpinner = true; 
    this.myService.getStuff().then(function(data) {
        _this.$scope.stuff = data;
        _this.$scope.showSpinner = false;
    });
});

这是完整的工作小提琴:http://jsfiddle.net/jeremylikness/PhZYb/

【讨论】:

    【解决方案2】:

    这样的事情应该对你有用。 $resource 实例返回一个您可以访问的承诺(无需手动注入 $q 服务):

        updateData: function() {
    
            var Data = API.update({ ... your opts ... });
    
            // access the built-in $promise 
            Data.$promise.then(function(res){
    
                // $broadcast from $rootScope
                $rootScope.$broadcast('Data.updateSuccess');
    
            }, function(err){
    
                 $rootScope.$broadcast('Data.updateError', err);
    
            });
        }
    

    从这些见解:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-07
      相关资源
      最近更新 更多