David Kethel
David Kethel

Reputation: 2550

How do I create a angular js service that makes a http request only once

I have the following angularjs service

var assetLookUpTransformService = function($http, $q) {
this.data = null;
var self = this;

this.doStuff = function() {

    var defer = $q.defer();

    if (self.data) {
        defer.resolve(self.data[0].DisplayName);
    } else {
        $http({
            url: '../AssetLookup/GetAssetLookUp',
            method: "GET"
        }).success(function(response) {
            self.data = response;
            defer.resolve(self.data[0].DisplayName);
        });
    }
        return defer.promise;
    }
}

It works ok, in that once the $http request has returned all subsequent calls to "doStuff" return data from data rather than make a new request.

Then problem I have is that I am making a bunch of calls right after each other on page load. And what is happening is that the first call to doStuff will make an $http request, but also any calls to dostuff that happen before the first http request returns will also make a $http request.

Is there a way to make the calls to doStuff "wait" for the outstanding $http request to return before making there own.

Or is there a way to ensure the $http request only ever happens once?

Upvotes: 1

Views: 83

Answers (2)

HankScorpio
HankScorpio

Reputation: 3651

Cache the promise, not the data. The data is encapsulated in the promise and will always be returned to whatever requests it.

var assetLookUpTransformService = function($http, $q) {
var self = this;

    this.doStuff = function() {
        if (!self.deferred) {
            self.deferred = $q.defer();

            $http({
                url: '../AssetLookup/GetAssetLookUp',
                method: "GET"
            }).success(function(response) {
                self.deferred.resolve(response[0].DisplayName);
            });
        }
        return self.deferred.promise;
    }
}

Upvotes: 3

rocketegg
rocketegg

Reputation: 414

Why don't you just make each of those calls after the first call to doStuff?

Example:

this.doStuff = function(afterRequests) {
   var defer = $q.defer();

if (self.data) {
    defer.resolve(self.data[0].DisplayName);
} else {
    $http({
        url: '../AssetLookup/GetAssetLookUp',
        method: "GET"
    }).success(function(response) {
        self.data = response;
        defer.resolve(self.data[0].DisplayName);
        //make each request in here.
        afterRequests.forEach(function(request) {
           $http(request).success(function(response) { 
           //use self.data here
           });
        });
    });
}
    return defer.promise;
}

If for some reason you have to make doStuff at the same time (e.g. it's very long running), then you could use $rootScope.$broadcast to target your controllers which may need to render the data.

Upvotes: 0

Related Questions