编写懒惰的ajax服务的最佳实践

时间:2015-12-22 09:06:49

标签: javascript angularjs ajax

在angular-js中编写懒惰ajax服务的最佳做法是什么?例如,我想创建资源,由于某种原因应该返回这样的承诺:

angular.module('MyModule',[])
  .factory('myService', function() {
    return {
      getData: function() {
          return $http.get('http://host/api/data');
      }
    }
  });

我想只加载一次这样的数据,那么实现它的最佳方法是什么? 我只有一个想法,这真的很难看:

angular.module('MyModule', [])
.factory('myService', function($q) {
    var dataResponse = null;
    return {
        getData: function() {
            if (dataResponse) {
                var def = $q.defer();
                def.resolve(dataResponse);
                return def.promise;
            }
            return $http.get('http://host/api/data');
        },
        setDataResponse: function(response) {
            dataResponse = response;
        }
    }
})
.controller('MyCtrl', function($scope, myService) {
    myService.getData().then(function(response) {
        myService.setDataResponse(response);
        $scope.data = response.data
    })
});

我不喜欢这部分:

var def = $q.defer();
def.resolve(dataResponse);
return def.promise;

而且我不喜欢每次调用getter时都必须编写响应设置器的事实,但我真的不知道如何更好地编写代码。

3 个答案:

答案 0 :(得分:2)

因为你不喜欢这个部分:

var def = $q.defer();
def.resolve(dataResponse);
return def.promise;

将其重写为:

return $q.resolve(dataResponse);

AngularJS< 1.4当()时调用resolve方法。

可以通过在' getData'中的服务内部缓存结果来修复其余代码。解决之前的方法。这不应该是来电者的责任。所以:

return {
    getData: function() {
        if (dataResponse !== null) {
            return $q.resolve(dataResponse);
        }

        return $http.get('http://host/api/data').then(onSuccess);

        function onSuccess(data){
            dataResponse = data;
            return data;
        }
    }
}

答案 1 :(得分:2)

您可以稍微清理一下记忆逻辑。

angular.module('MyModule', [])
.factory('myService', function($q) {
    var dataResponse = null;
    return {
        getData: function() {
            if (dataResponse) {
                return $q.when(dataResponse); // or $q.resolve for angular 1.4+
            }
            return $http.get('http://host/api/data').then(function(data) {
              dataResponse = data;
              return data;
            });
        },
    }
})
.controller('MyCtrl', function($scope, myService) {
    // use as normal. No need to write back
    myService.getData().then(function(response) {
        $scope.data = response.data
    })
});

答案 2 :(得分:0)

您应该使用$resource,这可以选择简单地缓存数据,并且更容易绑定到RESTapi。

否则你可以自己缓存数据:

angular.module('MyModule', [])
.factory('MyService', function($q) {
    var dataResponse;
    return {
        getData: function() {
            return $q(function(resolve, reject) {
                if(angular.isDefined(dataResponse)) {
                    resolve(dataResponse);
                } else {
                    $http
                        .get('http://host/api/data')
                        .then(function(response) {
                            dataResponse = response;
                            resolve(dataResponse);    
                        });
                }
            });
            if (dataResponse) {
                var def = $q.defer();
                def.resolve(dataResponse);
                return def.promise;
            }
            return $http.get('http://host/api/data');
        },
        setDataResponse: function(response) {
            dataResponse = response;
        }
    }
})
.controller('MyCtrl', function($scope, MyService) {
    MyService
        .getData()
        .then(function(response) {
            var vm = this;
            vm.data = response.data
        })
});

现在请注意,我将数据绑定到控制器(ViewModel的vm),因此您应该将模板重构为以下内容:

<ul ng-controller="MyCtrl as ctrl">
    <li ng-repeat="item in ctrl.data">
        {{ item.name }}: {{ item.price }}
    </li>
</ul>