AngularJS 数据在控制器之间、服务之间以及与 API 的共享
整合所有内容 - 控制器、服务、$http、缓存等等
背景
一个常见的问题是关于数据共享,我们应该如何从一些服务器 API 获取数据到 Angular 控制器,然后将这些数据与其它控制器共享。
不要直接使用 $http
有些人喜欢在控制器中使用 $http
直接调用他们的服务器端 API。
function DisplayDataController($http) {
$http.get(configuration.consts.baseApiUrl + 'ServerUrl/GetSomeValue', {id: id}).then(function (data) {
});
}
这样做有几个原因,是不好的做法
- 控制器应该只处理显示逻辑。
- 如果你想更改调用并将其在不同地方重用,则需要在所有位置进行更改。
- 每个控制器存储自己的数据,并且可能导致多次调用,而这些调用可以减少到一次。
使用 AngularJS 服务
首先,让我们将所有传出的 API 调用封装在一个单一的 facade 下,为此,我们将创建一个 AngularJS 服务。AngularJS 服务非常有用,特别是考虑到它实际上是一个单例,我们稍后会利用这一点。
MyModule.service('DataService', function ($http) {
this.GetSomeData = function(id) {
return $http.get(configuration.consts.baseApiUrl + 'ServerUrl/GetSomeData', {id: id});
};
});
MyModule.controller('DisplayDataController', function (DataService) {
DataService.GetSomeData(id).then(function (data) {
// Use the data
});
});
注意:请阅读以下文章,以了解如何跳过使用 data.data
(http 响应对象)并直接访问服务器的实际数据:https://codeproject.org.cn/Articles/1078528/AngularJS-Loader-and-Error-Handling-Infrastructure
我们所做的是创建一个调用 $http
的服务。现在控制器使用该服务,而不是直接使用 $http
。
但是,如果另一个控制器将使用此服务,它将再次调用服务器,当然我们可以设置 cache: true,但这只是一个简单的例子,在高度复杂的系统中会发生什么?
最终解决方案,带有缓存机制的服务
现在让我们为完整的解决方案添加一些缓存逻辑
MyModule.service('DataService', function ($http, $q) {
var cache = {};
return {
get: function(id) {
var deferred = $q.defer();
if (cache[id] != null) {
deferred.resolve(cache[id]);
} else {
$http.get(configuration.consts.baseApiUrl +
'ServerUrl/GetSomeData', {id: id}).then(function(data) {
cache[id] = data.data[0];
deferred.resolve(data.data[0]);
});
}
return deferred.promise;
}
};
});
所以我们在这里实现的是一个带有缓存的服务,现在我们可以从不同的控制器调用我们的“DataService
”,并共享相同的逻辑和数据。