title: How to wait for asynchronous http subscription to complete in multilevel nested function
body: <p>I am new to Rxjs. I am trying to implement a canActivate guard for my nativescript-angular app. Basically, if the user has JWT token in the storage, it will try to check for the JWT validity from the server, and land on the homepage if the token still valid, or redirect to the login page if its invalid. The following code works fine when the server is up, however, when the server is down, it will land on an incomplete homepage because data is not available to fetch from the server. This happen because the synchronous <code>if(this.authService.isLoggedIn())</code> do not wait for the asynchronous http call and return true (code below). I want it to redirect to login page instead of the homepage by blocking  when the server is down, I have tried various ways (even refactoring the code) but none of them works. <a href="https://stackoverflow.com/questions/45886395/wait-for-rxjs-operation-to-blocking">This</a> and <a href="https://stackoverflow.com/questions/44742091/how-to-call-an-async-method-in-canactivate-with-angular?rq=1">this</a> are quite similar to my case, but the solutions are not helpful. Here is my code:</p>
  
  <p>Edit:
  auth.service.ts (Updated)</p>
  
  <pre><code>import { getString, setString, remove } from 'application-settings';
  
  interface JWTResponse {
    status: string,
    success: string,
    user: any
  };
  export class AuthService {
    tokenKey: string = 'JWT';
    isAuthenticated: Boolean = false;
    username: Subject&lt;string&gt; = new Subject&lt;string&gt;();
    authToken: string = undefined;
  
    constructor(private http: HttpClient) { }
  
    loadUserCredentials() { //call from header component
      if(getString(this.tokenKey)){ //throw error for undefined
        var credentials = JSON.parse(getString(this.tokenKey));
        if (credentials &amp;&amp; credentials.username != undefined) {
          this.useCredentials(credentials);
          if (this.authToken)
            this.checkJWTtoken();
        }  
      }
    }  
  
    checkJWTtoken() {
      this.http.get&lt;JWTResponse&gt;(baseURL + 'users/checkJWTtoken') //call server asynchronously, bypassed by synchronous code in canActivate function
      .subscribe(res =&gt; {
        this.sendUsername(res.user.username);
      },
      err =&gt; {
        this.destroyUserCredentials();
      })
    }  
  
    useCredentials(credentials: any) {
      this.isAuthenticated = true;
      this.authToken = credentials.token;
      this.sendUsername(credentials.username);
    }  
  
    sendUsername(name: string) {
      this.username.next(name);
    }  
  
    isLoggedIn(): Boolean{
      return this.isAuthenticated;
    }
  
    destroyUserCredentials() {
      this.authToken = undefined;
      this.clearUsername();
      this.isAuthenticated = false;
      // remove("username");
      remove(this.tokenKey); 
    }
  
    clearUsername() {
      this.username.next(undefined);
    }  
  </code></pre>
  
  <p>auth-guard.service.ts</p>
  
  <pre><code> canActivate(route: ActivatedRouteSnapshot,
          state:RouterStateSnapshot): Observable&lt;boolean&gt; | Promise&lt;boolean&gt; | boolean{
  
              this.authService.loadUserCredentials(); //skip to next line while waiting for server response
              if(this.authService.isLoggedIn()){ //return true due useCredentials called in the loadUserCredentials
                  return true;
              }
              else{
                  this.routerExtensions.navigate(["/login"], { clearHistory: true })
                  return false;
              }
      }
  </code></pre>
  
  <p>app.routing.ts</p>
  
  <pre><code>const routes: Routes = [
      { path: "", redirectTo: "/home", pathMatch: "full" },
      { path: "login", component: LoginComponent },
      { path: "home", component: HomeComponent, canActivate: [AuthGuard] },
      { path: "test", component: TestComponent },
      // { path: "item/:id", component: ItemDetailComponent },
  ];
  </code></pre>
  
  <p>Edit2:
  I tried these code:</p>
  
  <p>auth-guard.service.ts</p>
  
  <pre><code>canActivate(route: ActivatedRouteSnapshot,
      state:RouterStateSnapshot): Observable&lt;boolean&gt; | Promise&lt;boolean&gt; | boolean{
  
      this.authService.loadUserCredentials();
      if(this.authService.isLoggedIn()){
          console.log("if");
          return true;
      }
      else{
          console.log("else");
          this.routerExtensions.navigate(["/login"], { clearHistory: true })
          return false;
      }
  }
  </code></pre>
  
  <p>auth.service.ts</p>
  
  <pre><code>  async checkJWTtoken() {
      console.log("checkJWTtoken1")    
      try{
        console.log("try1")
        let res = await this.http.get&lt;JWTResponse&gt;(baseURL + 'users/checkJWTtoken').toPromise();
        console.log("try2")
        this.sendUsername(res.user.username);
        console.log("try3")
      }
      catch(e){
        console.log(e);
        this.destroyUserCredentials();
      }
      console.log("checkJWTtoken2")    
    }  
  
  
    // checkJWTtoken() {
    //   this.http.get&lt;JWTResponse&gt;(baseURL + 'users/checkJWTtoken')
    //   .subscribe(res =&gt; {
    //     // console.log("JWT Token Valid: ", JSON.stringify(res));
    //     this.sendUsername(res.user.username);
    //   },
    //   err =&gt; {
    //     console.log("JWT Token invalid: ", err);
    //     this.destroyUserCredentials();
    //   })
    // }  
  </code></pre>
  
  <p>and here is the console output:</p>
  
  <pre><code>JS: Angular is running in the development mode. Call enableProdMode() to enable the production mode.
  JS: checkJWTtoken1
  JS: try1
  JS: if
  JS: ANGULAR BOOTSTRAP DONE. 6078
  JS: try2
  JS: try3
  JS: checkJWTtoken2
  </code></pre>
  
  <p>Edit3:</p>
  
  <p>tsconfig.json</p>
  
  <pre><code>{
      "compilerOptions": {
          "module": "commonjs",
          "target": "es5",
          "experimentalDecorators": true,
          "emitDecoratorMetadata": true,
          "noEmitHelpers": true,
          "noEmitOnError": true,
          "lib": [
              "es6",
              "dom",
              "es2015.iterable"
          ],
          "baseUrl": ".",
          "paths": {
              "*": [
                  "./node_modules/tns-core-modules/*",
                  "./node_modules/*"
              ]
          }
      },
      "exclude": [
          "node_modules",
          "platforms"
      ]
  }
  </code></pre>
  
  <p>Please advise and thanks in advance.</p>