0

My angular application is divided into 4 modules and all modules require user details so I am calling getUser method from each of the module. So when my application loads all 4 modules hit the getUser API simultaneously resulting in 4 get requests on server. How can I prevent this ? I am using singleton pattern in my getUser method so once my user gets loaded it will simply serve the user from an object. But that does not solves the problem if all modules request for the user simultaneously.

My code looks like this

getUser() {
let defer = this.q.defer();

if (!this.user) {
    this.http.get(`${this.config.apiHost}users`)
        .success(result => {
            this.user = result;

            this.rootScope.$broadcast('userFound', this.user);
            defer.resolve(this.user);
        })
        .error(err => defer.reject(err))
}
else {
    defer.resolve(this.user);
    this.rootScope.$broadcast('userFound', this.user);
}
return defer.promise;
}
6
  • Add the call inside a service. The service will check if the user object exists. If it is the case, it returns the object - If not, return the get call. OR you can cache the call Commented Feb 16, 2017 at 12:40
  • I already have the method defined in the service only and it checks if the user object exists or not. But when all modules try to get the user simultaneously then this approach does not works. Commented Feb 16, 2017 at 12:45
  • do you use ui-router? .. i can suggest to you to use a resolve method in the routing and pass the result of the request to yours controller .. Commented Feb 16, 2017 at 12:45
  • What do you mean by module ? Multiple parts of the same page ? If it is the case why don't you load once when landing on the page ? Commented Feb 16, 2017 at 12:46
  • I am using stateProvider for routing Commented Feb 16, 2017 at 12:47

3 Answers 3

1

By storing the current request in a variable the call to UserService.get will return the same request promise.

Then when the promise resolves, it will resolve to all your modules.

    angular.module('app').service('UserService', function ($http) {

    var self = this;

    var getRequestCache;

    /**
     * Will get the current logged in user
     * @return user
     */
    this.get = function () {
        if (getRequestCache) {
            return getRequestCache;
        }

        getRequestCache = $http({
            url: '/api/user',
            method: 'GET',
            cache: false
        }).then(function (response) {
            // clear request cache when request is done so that a new request can be called next time
            getRequestCache = undefined;
            return response.data;
        });

        return getRequestCache;
    };

});
Sign up to request clarification or add additional context in comments.

Comments

0

You are using ui-router for the routing. You can then use this to resolve the user when landing on the page.

In your routing config :

$stateProvider
    .state('myPage', {
        url: '/myPage',
        templateUrl: 'myPage.html',
        controller: 'myCtrl',
        resolve: {
            userDetails: ['UserService', function(UserService) {
                return UserService.getUserDetails();
            }],
        }
    })

In your controller

angular.module('myModule')
    .controller('myCtrl', ['userDetails', function(userDetails) {
        console.log(userDetails);
        }];

This will load the user details while loading the page.

Comments

0

I solved this problem by using defer object as a global object so that it only gets initialised once.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.