title: Trigger Angular app logic after Firebase notifications registration and device token
body: <p>I'm looking to implement this logic in my Angular 13 Ionic 6 app:
  Upon app start, obtain device token.
  With the device token, I do some logic (query the DB to see if this device is known or new) and based on the results - route to a page: Signup page for unknown devices, and some Home page for existing. Until either of these pages come up, I'll probably show a spinner or something.</p>
  <p><strong>I cannot reach a situation in which the appLauncher() function is called with a valid token.</strong>
  I tried by storing the token in local storage - but I couldn't async with the storage being populated.
  The last thing I tried (shown here) is using an @Output emitter - the appLauncher is never called.
  Here's what I have:</p>
  <p><strong>app.component.ts</strong> - Here I also tried nested Promises. I'm OK with the first promise resolved quickly if the token is already found in local storage, and only if this is first run - I will wait some time until this storage is populated. But calling appLauncher failed here too, and I believe it's not an elegant way to implement. I prefer reactive events running the show here.</p>
  <pre><code>import { Component } from '@angular/core';
  import { AlertController, Platform } from '@ionic/angular';
  import { Router } from '@angular/router';
  
  import { SplashScreen } from '@capacitor/splash-screen';
  
  import { FbNotificationsService } from './services/fb-notifications.service';
  import { TigergraphService } from &quot;./services/tigergraph.service&quot;;
  import { get, set, remove } from './services/storage.service';
  
  @Component({
    selector: 'app-root',
    templateUrl: 'app.component.html',
    styleUrls: ['app.component.scss'],
  })
  export class AppComponent {
    deviceId: string;
    private _tgdb;
    constructor(
      private platform: Platform,
      private fbNotifications: FbNotificationsService,
      private route: Router,
      public tgdb: TigergraphService,
      public LoggerService: LoggerService,
      private alertCtrl: AlertController
    ) {
      this.initializeApp();
    }
  
   
    initializeApp() {
      this.platform.ready().then(async (source) =&gt; {
        console.log(&quot;platform source: &quot; + source);
        // Trigger the push setup 
        this.fbNotifications.initPush();
  
        get('device-token').then(
          (res) =&gt; {
            if (res==null) {
              console.log('No token returned - need to wait for the promise to complete');
              
              return new Promise(function(resolve, reject) {
                setTimeout(function() {
                    // Fetch token again after a delay
                    get('device-token').then(
                      (res) =&gt; {
                        resolve(res);
                      }
                    )
                    
                 }, 15000);
            });
            } else {
              console.log('app main just received a device token: ', res.value);
              this.appLauncher(res.value);
            }
        },
          (err) =&gt; {
            console.error('Error in receiving device token in app main: ', err);
        }).then(function(resToken2: any) {
          console.log('Obtained the device token on second attempt: ', resToken2);
          if (resToken2) {
            this.appLauncher(resToken2);
          }        
      });
  
  
        try {
          await SplashScreen.hide();
         } catch (err) {
          console.log('This is normal in a browser: ', err);
         }
      });
    }
  
  
    deviceTokenReceived(event) {
      console.log('Device Token received from emitter: ', event);
      if (event) {
        this.appLauncher(event);
      }
    }
  
    //Based on deviceId and if existing user or not - route
    appLauncher(deviceId: string) {
      console.log('Entered appLauncher: ', deviceId);
      this._tgdb.runQuery(&quot;getPersonByDeviceId&quot;, {&quot;DeviceId&quot;: deviceId}).subscribe(
        res =&gt; {
          if(res == null){
            //No person found in DB - need registration routing
            console.log('No person found with DeviceID. Routing to signup');
            this.route.navigate(['/signup']); 
            
          } else {
            //person exists in db
            console.log('TG Query Result PErson by DeviceID: ' + JSON.stringify(res) + ' firstName: ' + res[0].vPerson[0].attributes.firstName);
            set('curr-person', res[0].vPerson[0].attributes); //Store locally for use throughout the app
            console.log('curr-person just saved');
            //Rout based on user type
            
          }
        },
        err =&gt; {
          console.log('TG Query Error: ' + err.description);
          //Route to some error page?
          this.showAlert(&quot;Network Error&quot;, &quot;Ooooops. I can't find any Internet at this time&quot;);
        }
    );
    }
  }
  </code></pre>
  <p><strong>app.component.html</strong> - only used to capture the emitted @Output variable event - but never really works:</p>
  <pre><code>&lt;ion-app&gt;
    &lt;ion-item (deviceId)=&quot;deviceTokenReceived($event)&quot;&gt;&lt;/ion-item&gt;
    &lt;ion-router-outlet&gt;&lt;/ion-router-outlet&gt;
  &lt;/ion-app&gt;
  </code></pre>
  <p><strong>The Firebase service:</strong></p>
  <pre><code>import { EventEmitter, Injectable, Output } from '@angular/core';
  import {ActionPerformed, PushNotifications, PushNotificationSchema, Token} from '@capacitor/push-notifications';
  import {  Capacitor } from '@capacitor/core';
  
  import { get, set, remove } from './storage.service';
  
  @Injectable({
    providedIn: 'root'
  })
  export class FbNotificationsService {
  
    @Output('deviceId') deviceId = new EventEmitter&lt;string&gt;();
  
    constructor() {}
   
    initPush() {
      if (Capacitor.getPlatform() !== 'web') {
        this.registerPush()
      } else {
        
      }
    }
   
    private registerPush() {
      PushNotifications.requestPermissions().then((permission) =&gt; {
        if (permission.receive === 'granted') {
          // Register with Apple / Google to receive push via APNS/FCM
          console.log('FB Permission granted');
          PushNotifications.register(); //Registers app to receive notifications
        } else {
          // No permission for push granted by user on iOS
          console.log('FB NO permissions granted');
        }
      });
   
      PushNotifications.addListener(
        'registration',
        (token: Token) =&gt; {
          console.log('My token: ' + JSON.stringify(token));
          //This is the device token.
          this.deviceId.emit(token.value);
          set('device-token', token.value).then( () =&gt; {
            remove('curr-person'); //clear local store of current person in app init
          }); //to be picked up in registration
          
        });
   
      PushNotifications.addListener('registrationError', (error: any) =&gt; {
        console.log('Error: ' + JSON.stringify(error));
        //Alert that the registration of this device for notifications failed
      });
   
    }
  }
  </code></pre>
  <p>The Storage service is skipped here for brevity, it's just uses the Storage service from @capacitor/storage to get/set the token values.</p>
  <p><strong>Please, what's the right approach for this to work?</strong>
  Thanks!</p>