Angular 5 - 如何等待异步方法的返回值

时间:2018-06-08 16:28:27

标签: angular asynchronous observable

我的根ngOnInit的{​​{1}}方法正在执行以下身份验证:

AppComponent

以下是 token: SessionToken; authenticated: boolean; constructor( private authService: AuthenticationService, private router: Router) {} ngOnInit() { this.authService.authenticate().subscribe(token => { if (token != null) { // authenticated this.token = token; this.authenticated = true; } else { // not authenticated this.authenticated = false; } }); } 中的authenticate方法:

authService

然后在同一个服务中,我还有另一个方法,通过检查从// Authenticate user. Returns non-null token if authenticated, null token otherwise. token: MyCustomToken; authenticate(): Observable<MyCustomToken> { return this.http.get<SessionToken>(this.url) .pipe( tap(token => this.token = token), catchError(this.handleError<SessionToken>('authenticate')) ); } 调用返回的令牌是否为null来检查用户是否经过身份验证:

authenticate

最后,在我的身份验证防护的public isAuthenticated(): boolean { if (this.token != null) { return true; } else { return false; } } 方法中,我想调用canActivate方法来检查用户在显示页面之前是否经过身份验证:

isAuthenticated

问题是,canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean>|boolean { console.log("in canActivate() of authentication guard."); let val = this.authService.isAuthenticated(); console.log(`Is authenticated? ${val}`); // printing false, even though the server returned a non-null token when I called authenticate in AppComponent return val; } 方法中的this.authService.isAuthenticated()返回false,即使我在AppComponent中调用authenticate时服务器返回了非空令牌。

canActivate的{​​{1}}调用中,从服务器返回令牌之前,canActivate被称为正在被称为,因为{ {1}}是异步调用。

那么我有没有办法等待异步调用完成或其他一些解决方法?

1 个答案:

答案 0 :(得分:1)

这是一个“伪”代码,它应该有助于指导您如何编写一些涉及大量异步的启动循环方法。这个通常位于app.component.ts中。

下面还假设您的应用程序具有某种形式的本地持久性(诸如localForage等库,它可以抽象并使得在客户端上访问indexeddb或websql持久性变得容易)。

本地持久性对于帮助存储用户上下文数据(如是否显示intro等)非常重要,用于定义启动周期:

  initApp() {
    // this below collects all locally persistent data about user:
    this.getAppContext().then(()=>{
      // here some additional activities depending on your app:
      this.statusBar.hide();
      this.splashScreen.hide();
      // then we proceed with startup cycle:
      this.startUpCycle();
    })
  }

  // gather application context: userData, appIsOnline, JWT token, appIsCordova etc
  async getAppContext() {
    // foundation here is a global service that is available across the app:
    const promise = await this.foundation.storage.get("___userData")
    if (promise) {
      this.foundation.userData = promise;
      this.foundation.userID = promise.user._id;
      this.foundation.introShown - promise.introShown;
      this.foundation.appHasUserData = true;
    } else {
      this.foundation.appHasUserData = false;
    }
  };

  startUpCycle() {
  // if no data stored locally - we direct user to signup / intro page:
  if (!this.foundation.appHasUserData) {
      set signup page as the root page
      END
      // if data was persisted before:
  } else {
      (initalize local storage with user data).then(() => {
        (load additional user data like documents etc).then(() => {
          (check JWT as part of this.foundation.userData).subscribe(() => {
            do stuff
          set root page as the main page
            initialise FCM / notifications
            sync to remote database
          }, (err) => {
            set root page to login page
          })
        }
      })
    })
  }

理想情况下,我建议在编写代码之前草拟具有应用程序中应该发生的内容和顺序的逻辑的图表。示例(它的离线/角度应用程序可以离线,也可以在cordova / native上);

enter image description here