Looking to implement a simple caching mechanism in an AngularJS service for data retrieved from HTTP requests. The goal is to always reference the same object to avoid duplicating requests. Below is an example code snippet showcasing the issue at hand.
Link to the JSFiddle code illustrating the problem
The UsersModel
service fetches user data via HTTP requests, with this data being shared across controllers. The aim is to maintain a consistent reference to the data. A check is added before calling UsersModel.getUsers()
to see if any cached data exists; if not, a new request is made. This service is then injected into three different controllers. The first two controllers make the call immediately upon page load, while the third does so upon button click. The issue arises when the first two controllers simultaneously trigger the UsersModel.getUsers()
function, resulting in separate HTTP requests and referencing different user objects.
The question is how to ensure that simultaneous calls to UsersModel.getUsers()
return the same data object consistently.
app.js
var APP = angular.module('APP', []);
APP.SidebarCtrl = function ($scope, UsersModel) {
var sidebarCtrl = this;
UsersModel.getUsers()
.then(function (users) {
sidebarCtrl.users = users;
});
};
APP.ContentCtrl = function ($scope, UsersModel) {
var contentCtrl = this;
UsersModel.getUsers()
.then(function (users) {
contentCtrl.users = users;
});
};
APP.FootCtrl = function ($scope, UsersModel) {
var footCtrl = this;
function load() {
UsersModel.getUsers()
.then(function (users) {
footCtrl.users = users;
});
}
footCtrl.load = load
};
APP.service('UsersModel', function ($http, $q) {
var model = this,
URLS = {
FETCH: 'http://api.randomuser.me/'
},
users;
function extract(result) {
return result.data.results['0'].user.email;
}
function cacheUsers(result) {
users = extract(result);
return users;
}
model.getUsers = function () {
return (users) ? $q.when(users) : $http.get(URLS.FETCH).then(cacheUsers);
};
});
Index.html
<div ng-app="APP">
<div ng-controller="APP.SidebarCtrl as sidebarCtrl">
<h1>{{ sidebarCtrl.users }}</h1>
</div>
<div ng-controller="APP.ContentCtrl as contentCtrl">
<h1>{{ contentCtrl.users }}</h1>
</div>
<div ng-controller="APP.FootCtrl as footCtrl">
<h1>{{ footCtrl.users }}</h1>
<button ng-click="footCtrl.load()" type="button">Load</button>
</div>
</div>