AngularJS - 如何缓存服务的ajax结果以在控制器中重用

时间:2017-01-15 21:36:29

标签: javascript jquery angularjs ajax

我建议使用Angular服务来集中存储在我的控制器中的许多重复功能,所以我现在正在使用服务重写我的代码。

起初看起来很简单,但似乎找不到一个好的结构来获取我的ajax数据(只有一次),然后将它存储在我的服务器中,以便我的控制器在需要时重用缓存的数据。目前我不断收到错误说:TypeError: Cannot read property 'sayHello' of undefined

我相信这是因为在控制器加载之前,通过我的服务获取我的ajax数据是一个延迟。我不太确定如何优化这一点。有人会有更好的结构吗?

服务:     app.service(' MyService',功能($ http){

    this.sayHello = function () {

        var deferred = $q.defer();

        $http({
            method: 'GET',  
            url: 'AJAX PATH',
            headers: { "Accept": "application/json;odata=verbose;charset=utf-8"} 
        }).then(function(data){

            var configurations = data;
            var configurations.data_result_1 = configurations.data_result_1.split("\r\n");
            var configurations.data_result_2 = configurations.data_result_2.split("\r\n");
            deferred.resolve(configurations);
        }

        return deferred.promise;
    };

    this.sayHello(); //Run the function upon page laod.

});

控制器:

app.controller('AppController', function (MyService, $scope) {

    $scope.configurations = null;
    $scope.configurations = function() { MyService.sayHello() }; 

});

3 个答案:

答案 0 :(得分:2)

我建议您使用其他方式来声明服务:

 app.factory("MyService", function($http){
   var configurations = {};

 $http({
        method: 'GET',  
        url: 'AJAX PATH',
        headers: { "Accept": "application/json;odata=verbose;charset=utf-8"} 
    }).then(function(data){

         configurations = data;
         configurations.data_result_1 =                                              configurations.data_result_1.split("\r\n");
         configurations.data_result_2 = configurations.data_result_2.split("\r\n");

    });
 return {

  getConfigurations: function(){
    return configurations;
    }

}

在您的控制器中,您可以使用$ watch,然后当配置对象发生更改时,您将获取以下信息:

 .controller("YourCtrl", function($scope,MyService){
   var vm = this;
   vm.configurations = {};

     $scope.$watchCollection(function () { return MyService.getConfigurations()},function(newValue){
  vm.configurations = newValue;
});

答案 1 :(得分:1)

完全同意Bri4n关于工厂中的商店配置。不同意控制器,因为你说你不想看,但只加载数据一次。

但是你的$ http已经返回了一个承诺,所以Brian说这很好(只有$ q在这里没用,所以你可以从注入中删除它)。我只是在函数中包装http调用,而公开的函数只是检查配置是否已经加载。如果是,只返回配置,否则加载它然后返回它。

 app.factory("MyService", function($http,$q){
   var configurations = {};

 function loadConfig(){
 $http({
        method: 'GET',  
        url: 'AJAX PATH',
        headers: { "Accept": "application/json;odata=verbose;charset=utf-8"} 
    }).then(function(data){

         configurations = data;
         configurations.data_result_1 =                                              configurations.data_result_1.split("\r\n");
         configurations.data_result_2 = configurations.data_result_2.split("\r\n");

    });

}      返回{

  getConfigurations: function(){
    If( !!configurations ){
        return configurations;
    }
    //Else loadConfig.then return configurations 
    }

}

在您的控制器中,您只需获取配置,而无需知道它是否已加载。

 .controller("YourCtrl", function(MyService){
   var vm = this;
   // If configurations already loaded return config, else load configurations and return configurations.
   vm.configurations = MyService.getConfigurations();

我在手机上写字,所以我的代码不完美,我写不出来。

答案 2 :(得分:0)

好的,第二个想法,看起来你没有正确使用依赖数组表示法。将您的代码更改为:

app.service('MyService', ['$http', function ($http) {
  // do your stuff here
}]);

和控制器:

app.controller('AppController', ['MyService', '$scope', function(MyService, $scope) {

 // do your stuff here

}]);