2017-01-15 45 views
0

我被推薦使用Angular服務來集中存儲在我的控制器中的許多重複功能,所以我現在正在使用服務重寫我的代碼。AngularJS - 如何緩存服務的ajax結果在控制器中重用

它看起來很簡單,但似乎找不到一個好的結構來獲取我的ajax數據(只有一次),然後將其存儲在我的服務中,以供控制器在需要時重用緩存數據。此刻,我不斷收到錯誤消息:TypeError: Cannot read property 'sayHello' of undefined

我相信這是因爲在控制器加載之前,theres會延遲通過我的服務獲取我的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() }; 

}); 
+0

代碼結構中存在問題,但不足以導致該錯誤。你確定這是引發錯誤的版本嗎? – charlietfl

+0

也許看看使用CacheFactory作爲響應。或者在你的http請求中指定高速緩存,這樣你可以再次調用它,並且只需要爲緩存結果提供服務,而不是發出另一個http請求。 https://docs.angularjs.org/api/ng/service/$http – haxxxton

回答

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

我在我的手機上寫字,所以我的代碼不完美我無法正確寫入。

+0

你仍然必須實現註釋行// //否則loadConfig.then返回配置 – Sphinx117

0

OK,經過再三考慮,它看起來像您不使用將您的代碼更改爲:

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

以及對於控制器:

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

// do your stuff here 

}]); 
+0

服務顯然是在OP代碼中注入控制器。訂單不相關,因爲角度引導不會發生,直到dom內容加載,這意味着所有組件將被註冊之前,他們被呼籲 – charlietfl

+0

我不是指「app.controller('AppController',function(MyService,$範圍)「,因爲我可以清楚地看到他已經注入了它,我說Angular無法將它注入到控制器中,因爲包含服務代碼的文件可能會在文件與控制器 –

+0

之間得到內部角'未知提供者'錯誤,如果是這種情況,我不認爲你理解引導過程,當它發生時 – charlietfl

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

}

在你的控制器,你可以使用$手錶,那麼當配置對象,您需要更改信息:

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

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