Background
A common issue that people discuss is about data sharing, how should we get data from some server API to an angular controller and then share this data with other controllers.
Do Not Use $http Directly
Some people like to use $http
in the controller to directly call their server side API.
function DisplayDataController($http) {
$http.get(configuration.consts.baseApiUrl + 'ServerUrl/GetSomeValue', {id: id}).then(function (data) {
});
}
This is bad practice for a few reasons:
- The controller should handle display logic only.
- If you want to change the call and reuse it in different places, you need to change it in all locations.
- Each controller stores its own data and may potentially cost in multiple calls that can be minimized to one.
Using AngularJS Service
First, let's start to encapsulate under a single facade all of the outgoing API calls, for this, we will create an angularJS service. A service in angular is very useful especially considering the fact that it's actually a singleton, we will use this to our advantage later on.
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) {
});
});
Note: Read the following article in order to understand how to skip using data.data
(the http response object) and simply access the actual data from the server: http://www.codeproject.com/Articles/1078528/AngularJS-Loader-and-Error-Handling-Infrastructure
What we have done is create a service which calls $http
. Now the controller uses the service and not directly the $http
.
But if a different controller will use this service, it will call the server again, sure we can set cache: true, but this is a simple example, what will happen in a highly complex system?
Final Solution, Service With Caching Mechanism
Now let's add some caching logic for the complete solution:
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;
}
};
});
So what we've accomplished here is a service with a cache, now we can call our "DataService
" from different controllers and share the same logic and data.