el_konor el_konor - 2 months ago 5
AngularJS Question

Prevent service from multiple server loads

I've got an angular service MyService
There is get method inside it. It get's info from server and sets it to local variable if variable is undefined, overwise return variable

export class MyService{
private userSettings: UserSettings;
private updateProcessing: boolean = false;
private deferred : any;

constructor(
private $http: ng.IHttpService,
private $q: ng.IQService,
private $log: ng.ILogService) {
}


public get(fromServer: boolean = false) {
var self = this;

if (self.updateProcessing) {
return self.deferred.promise;
}
else if (!self.userSettings || fromServer) {
return self.getFromServer();
} else
return self.$q.resolve(self.userSettings);
}

private getFromServer(): ng.IPromise<any> {
var self = this;
self.updateProcessing = true;
self.deferred = self.$q.defer();
var url = self.getSettingsUrl();

self.$http.get(url).then(
(result: any) => {
self.userSettings = result.data;
self.updateProcessing = false;
self.deferred.resolve(result.data);
},
error => {
this.$log.error(error);
self.updateProcessing = false;
self.deferred.reject(error);
}
);

return self.deferred.promise;
}
}


when I pass this service to 3 different controllers, they all get variable value from server.
I'm trying to save promise and if request is already prosessing whait while it resolves and do not create new one.
Right now with code I posted I do in my controllers

this.MyService.get().then(()=>{
});


and never get inside then callback.
If it's important, I use version: "1.5.8" of angular library.

Answer

You can share the same promise. Also note that $http already returns promise so using $q to create a new one is an anti-pattern

private getFromServer(): ng.IPromise < any > {
  var self = this;
  self.updateProcessing = true;
  // if promise not stored need to create it
  if (!self.storedPromise) {    
    var url = self.getSettingsUrl();    
    self.storedPromise = self.$http.get(url).then(
      (result: any) => {
        self.userSettings = result.data;
        self.updateProcessing = false;
        return self.userSettings;
      },
      catch => {
        this.$log.error(error);
        self.updateProcessing = false;
        return self.$q.reject(error);
      }
    );
  }
  // return the stored promise
  return self.storedPromise;
}

Now the first call to this method will create the promise and subsequent calls will return the same one

Comments