Have multiple calls wait on the same promise in Angular
Asked Answered
D

2

5

I have multiple controllers on a page that use the same service, for the sake of example we will call the service USER.

The first time the USER.getUser() is called it does an $http request to GET data on the user. After the call is completed it stores the data in USER.data. If another call is made to USER.getUser() it checks if there is data in USER.data and if there is data it returns that instead of making the call.

My problem is that the calls to USER.getUser() happen so quickly that USER.data does not have any data so it fires the $http call again.

Here is what I have for the user factory right now:

.factory("user", function($http, $q){
    return {
        getUser: function(){
            var that = this;
            var deferred = $q.defer();
            if(that.data){
                deferred.resolve(that.data);
            } else {
                $http.get("/my/url")
                .success(function(res){
                    that.data = res;
                    deferred.resolve(that.data);
                });
            }
            return deferred.promise;
        }
    }
});

I hope my question makes sense. Any help would be much appreciated.

Dibble answered 2/4, 2015 at 19:39 Comment(0)
C
10

Does this work for you?

.factory("user", function($http, $q) {
        var userPromise;

        return {
            getUser: function () {
                if (userPromise) {
                    return userPromise;
                }

                userPromise = $http
                    .get("/my/url")
                    .then(function(res) {
                        return res.data;
                    });

                return userPromise;
            }
        }
    })
Cormack answered 2/4, 2015 at 19:44 Comment(2)
Is there a name for this pattern? It's a good one. I overlooked this for a long time until I noticed that re-using controllers meant several calls to the same service.Lumberyard
@MuraliVP you could also remove $q from parameters now :)Cystine
B
1

$http already returns the promise for you, even more, in 2 useful types: success & error. So basically, the option that @kfis offered does NOT catch errors and not flexible. You could write something simple:

.factory('user', function($http) {
    return {
       getUser: function() {
          $http.get('/my/url/')
             .success(function(data) {
                return data;
             })
             .error(function(err) {
                // error handler
             })
       }
    }
})
Borehole answered 5/7, 2015 at 10:50 Comment(1)
I think the idea was to not invoke multiple HTTP requests for each call to getUser(). With this solution each call to getUser() would cause a new HTTP request to be invoked.Fiesole

© 2022 - 2024 — McMap. All rights reserved.