简体   繁体   English

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

[英]AngularJS - How to cache service`s ajax result to reuse in controller

I was recomended to use Angular services in order to centralize many repetative functions that were store in my controller, so I am rewriting my code using services now. 建议我使用Angular服务,以便集中存储在控制器中的许多重复功能,因此现在我要使用服务来重写代码。

It seemed simple at first but cant seem to find a good structure to fetch my ajax data (only once), then store it in my service for my controller to reuse the cached data when ever it needs it. 乍一看似乎很简单,但似乎找不到一个好的结构来获取我的ajax数据(仅一次),然后将其存储在我的服务中,以供我的控制器在需要时重用缓存的数据。 At the moment I keep getting errors saying: TypeError: Cannot read property 'sayHello' of undefined . 目前,我不断收到错误消息: TypeError: Cannot read property 'sayHello' of undefined

I believe this is because theres is a delay to fetch my ajax data via my service before the controller loads. 我相信这是因为在控制器加载之前通过我的服务获取我的ajax数据存在延迟。 Im not quite certain how I can optimize this. 我不太确定如何优化这一点。 Would anyone have a better stucture to this? 有人对此有更好的安排吗?

Service: app.service('MyService', function ($http) { 服务: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.

});

Controller: 控制器:

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

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

});

I recommend you to use another way to declare the service: 我建议您使用另一种方式声明服务:

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

} }

In your controller you can use a $watch, then when the configurations objects changes you take the information: 在您的控制器中,您可以使用$ watch,然后在配置对象更改时,获取以下信息:

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

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

Totally agree with Bri4n about store configuration in the factory. 对于工厂中的商店配置,完全同意Bri4n。 Not agree about the controller because you said you don't want to watch, but only load data once. 对控制器不满意,因为您说过不想观看,而只加载一次数据。

But you $http already return a promise so as Brian said this is nice (just $q is useless here so you can delete it from injection). 但是您$ http已经返回了一个承诺,因此正如Brian所说的那样(只是$ q在这里没有用,因此您可以从注入中删除它)。 And I just wrapped http call in function, and the exposed function just check if configurations are already loaded. 我只是将http调用包装在函数中,而暴露的函数只是检查配置是否已加载。 If yes, just return configurations else load it and then return it. 如果是,则只需返回配置,否则将其加载然后返回。

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

    });

} return { }返回{

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

} }

In your controller you can just get config without need to know if it is already loaded. 在您的控制器中,您只需获取配置即可,而无需知道它是否已经加载。

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

I write on my phone so my code is not perfect I can't write properly. 我在手机上书写,所以我的代码不够完美,无法正确编写。

OK, on second thought, it looks like you are not using the dependency array notation properly. 好的,再三考虑,您似乎没有正确使用依赖项数组表示法。 Change your code to: 将您的代码更改为:

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

and for the controller: 对于控制器:

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

 // do your stuff here

}]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM