0

Angular defines a run() block for an application module. This runs after config() and before any controllers and directives are loaded.

Is there a step in the lifecycle to run something after all controllers, directives, services, etc are loaded?

I need this in order to broadcast a message in my authorization pubsub service, and I want to ensure that everything is loaded before I publish the message. While I can check authentication in the run block (basically, just checking localstorage for a JWT via my authentication service), if I publish in the run() block I can't be sure if everything has loaded. I'm wondering if Angular exposes anything like this or whether I need to find a different solution.

Thanks!

  • I'd say that you may run into problems, since some controllers may not load until user action. For example, you may ng-repeat to create multiple instances of a directive. ng-repeat will create new instances of the directive over time, potentially generating new scopes,etc. – jazeee Dec 11 '14 at 18:17
  • In your comment, you indicate that you want to publish authentication information. I'd recommend using a service for that, which other services or controllers inject in order to determine authentication state. This would reliably provide the correct information to the dependencies. You can create an Authentication Service that returns a promise. Everyone can then react based on the outcome of that promise. – jazeee Dec 11 '14 at 18:21
  • @jazeee My authentication service returns a promise, as it's used to authenticate to the server. However, my authorization service is responsible for checking whether we have an authorized user at any given time (via JWT) and what that user's permissions are. I'm using pubsub/broadcast because permissions and login status can change at any time; thus, promises don't really work here (as I need to listen for changes). If a change happens, I broadcast that event so that everything in the application can respond accordingly. The problem I'm having is doing that on load. –  Dec 11 '14 at 19:03
  • Incidentally, `$timeout` with a zero count does seem to work here in the run block, but it's a naive implementation (and there's a display flicker). I don't think it's a guaranteed solution. –  Dec 11 '14 at 19:04
  • Perhaps a chicken-egg problem. One way I could think of is "Publish a notice that tells listeners to check for a new update" and also "Every listener checks for Auth status on instantiation". This combination addresses the two scenarios. For example. If service1 starts before Auth, it will be notified when Authentication occurs. If Controller starts after Auth, it will check for state, but also will listen for later changes. If Auth changes, it will notify all listeners. In other words, break it up into "listen to events", but also "initialize when created". Perhaps create AuthState service – jazeee Dec 12 '14 at 19:54

1 Answers1

0

An optional answer, taken from here

You can use a custom postDigest callback. if you need only the first postDigest callback, add a flag to indicate it happened

function postDigest(callback){    
  var unregister = $rootScope.$watch(function(){  
    unregister();
    $timeout(function(){
      callback();
      postDigest(callback);
    },0,false);       
  });
}

postDigest(function(){
  console.log('do something');
})
Community
  • 1
  • 1
Ofer Segev
  • 5,094
  • 2
  • 22
  • 22