0

I want build some simple cache in Angularjs service for data provide from http request. Additional I want always get reference to the same object. I prepare example code to illustrate my thinking and problem which I have now.

jsfiddle code illustrate problem

I have service UsersModel which provide me user from http request.This user data are shared between controllers. So want to have always reference to same data. I add to him simple logic. Before UsersModel.getUsers() call service check if exist any data from previous call, if exist return him, if not do a http request. I inject that service in tree controller. In first two controllers UsersModel.getUsers() is call immediately after page load. In last after click on button. Problem is when two first controller call UsersModel.getUsers() in the same time. Then any cached data don't exist and both do http request After that I have in first two controller reference to different user objects. We can see this clicking on load button.

And now my question. How to make this work for the simultaneous first call UsersModel.getUsers() and always have reference to the same object data.

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>

jsfiddle code illustrate problem

mbury
  • 33
  • 1
  • 6
  • 1
    seems like built-in angular [cache](https://docs.angularjs.org/api/ng/service/$http#caching) is perfect solution of your problem – Andrei Lesnitsky Feb 09 '15 at 15:49
  • Agree with @AndreiVolchenko there's no need for building a new cache implementation when doing http calls – pedrommuller Feb 09 '15 at 15:56
  • @AndreiVolchenko When I change 'http.get(URLS.FETCH, { cache: true}).then(cacheBanks)' I got the same data but reference to different object. So it is not solution. I mentioned this in a question. – mbury Feb 09 '15 at 16:07
  • @Andrei Volchenko New code for you: [jsfiddle code](http://jsfiddle.net/mbury/daxep9ut/3/) I have not shared data between controllers with yours solution. – mbury Feb 09 '15 at 16:26
  • possible duplicate of [Caching a promise object in AngularJS service](http://stackoverflow.com/q/18744830/1048572) – Bergi Feb 09 '15 at 19:40

1 Answers1

0

You can modify your functions as follows:

function cacheUsers(result) {
    return (users) ? users : users = extract(result); 
} 

and

model.getUsers = function () { 
    return (users) ? $q.when(users) : $http.get(URLS.FETCH, {cache: true}).then(cacheUsers); 
}; 

It provides additional cache check after fetch and enables built-in cache for the object.

I suggest you to read http://www.webdeveasy.com/angularjs-data-model/

Piotr Surma
  • 304
  • 1
  • 5
  • 12