首页 > 解决方案 > 如何在 Angular 服务中直接使用 .subscribe?

问题描述

解决了

我在 Angular 中实现用户的状态:isLogged true/false。

因此,无论我是哪个组件,我都会验证用户是否已登录以显示或隐藏内容。为此,我不想只控制 accessToken 是否在本地存储中,但我会使用 authService 检查它是否向服务器询问(使用 Http 请求)。所以我希望 authService 中的 isLogged() 只返回 true/false 或设置布尔值 true/false。通常我在组件的 .subscribe 中处理“res”和“err”,但我不会在每个组件中重复它。问题是我不知道如何在服务中直接使用 .subscribe 。

我正在使用此解决方案的那一刻。它有效,但我一点也不喜欢它!

isLogged() {
  return this.http
    .get<any>(this.isLoggedUrl)
    .pipe(catchError(this.errorHandler));
}

// I call this method in each component that needs to know if user is logged
isLoggedResHandle() {
  this.isLogged().subscribe(
    (res) => {
      if (res.status == 200) {
        this.loggedIn = true;
      }
    },
    (err) => {
      if (err.error.message == 'TokenExpiredError') {
        this.loggedIn = false;
        //DO.. try refresh token. if refreshed: this.loggedIn = true
      } else {
        // for any other errors:
        this.loggedIn = false;
      }
    }
  );
}

解决方案

auth.service.ts

isLogged() {
    const accessToken = this.getAccessToken;
    if (typeof accessToken === 'undefined' || accessToken === null) {
      console.log('pieroooooooooo');
      this.loggedIn = false;
      return;
    }

    return this.http
      .get<any>(this.isLoggedUrl)
      .pipe(catchError(this.errorHandler))
      .subscribe(
        (res) => {
          if (res.status == 200) {
            this.loggedIn = true;
          }
        },
        (err) => {
          if (err.error.message == 'TokenExpiredError') {
            const refreshToken = this.getRefreshToken;
            if (typeof refreshToken !== 'undefined' || refreshToken !== null) {
              this.loggedIn = false;
            }

            this.loggedIn = false;
            // TODO: try to refresh it
          } else {
            this.loggedIn = false;
          }
        }
      );
  }

  getIsLogged() {
    return this.loggedIn;
  }

header.component.ts 或我想要的任何组件,例如:

<button class="btn btn-light my-2 my-sm-0" id="cartBtn" *ngIf="authService.getIsLogged()" [routerLink]="'/profile'"
      type="submit">
      <i class="fas fa-shopping-cart"></i>
      Mio Profilo
</button>

app.component.ts // 在刷新后保持“用户状态”更新:

export class AppComponent implements OnInit {
  constructor(private authService: AuthService) {}

  ngOnInit(): void {
    this.authService.isLogged();
  }
}

标签: angularauthenticationrxjssubscribe

解决方案


解决方案可以是ParentComponentClass实现isLoggedResHandle逻辑的解决方案,并且每个需要它的组件都可以扩展类。

class ParentWithIsLoggedLogicCompoent {
  loggedIn = false
  
  constructor(private isLogged: IsLoggedService) {}

  isLoggedResHandle() {
    this.isLogged().subscribe(
      isLogged => this.loggedIn = isLogged,
      error => this.loggedIn = false
    )
  }
}

class YourOtherComponent extends ParentWithIsLoggedLogicCompoent implements OnInit {
  ngOnInit() {
    this.isLoggedResHandle();
  }
}

您可以使用运算符将​​重试逻辑提取到服务中retryWhen。我不确定语法是否良好,但它会是这样的:

isLogged() {
  return this.http
    .get<any>(this.isLoggedUrl)
    .pipe(
      retryWhen(errors => {
        errors.switchMap(error => {
          if(errors.error.message != 'TokenExpiredError') {
            throw errors
          }

          //DO.. try refresh token. if refreshed: this.loggedIn = true
        })
      }),    
      catchError(this.errorHandler)
    );
}

推荐阅读