jonhobbs jonhobbs - 12 days ago 6
AngularJS Question

Angular promise .then() repeated?

I have a function which returns a promise which is resolved if the user is currently logged in, or waits to resolve once the user has logged in. SO you can do this...

myService.waitForLogin().then(function(){
// Subscribe to pusher.com events
});


I then use a similar call to unsubscribe from events when the user logs out.

The trouble is that I want to run my .then() code every time the user logs in, so the process is....


  • If the user is logged in, run the code.

  • If not, wait till they log in, then run the code.

  • If they log out then back in again, run the code again.



I was originally using $rootscope.$on to listen to login/out events which worked well for the repeated occurrences, but I needed it to be promise based in case the user was already logged in.

Here is my code:

var defer = $q.defer();

if(isLoggedIn()){
defer.resolve();
}

else{

var offLoggedInTrue = $rootScope.$on('loggedin-true', function(){
defer.resolve();
offLoggedInTrue();
});

}

return defer.promise;

Answer

You can use the promise to controll the login status by storing a deferred on your service, and then return the promise through your method waitForLogin(). However, instead of resolving the promise, you could just notify it, once you resolve the login promise it won't be resolved again, so you can notify and reuse it many times as you can.

Note: this is a solution using promises, however you may find better use events instead, it's easier to maintain in my opinion.

For example:

angular.module('myApp', [])
  .service('LoginStatusService', function($q) {

    // store a deferred to represent the login resolution state
    var loginDeferred = $q.defer();

    // the getter method to yout login promise
    this.waitForLogin = function() {
      return loginDeferred.promise;
    };

    // an example login method from where you could notify the login promise
    this.login = function(login, password) {
      /// do async login things and then
      loginDeferred.notify();
    };

    // when the deferred may need to got reseted
    this.logoff = function(login, password) {
      /// do logoff things and then
      // loginPromise = $q.defer();
    };
  })

Then on your controller or whatever provider you want you can inject the service and use it like so:

  .controller('MyController', function(LoginStatusService) {

    LoginStatusService.waitForLogin().then(null, null, function () {
      // do your subscribe stuff here
    });
  });
Comments