如何直接在Angular服务中使用.subscribe?

时间:2020-09-12 12:40:51

标签: angular authentication rxjs subscribe

已解决

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

因此,无论我在哪里,都将验证用户是否已登录以显示或隐藏内容。 为此,我不希望仅控制accessToken是否在localstorage中,但我会使用authService来检查它是否要求服务器(带有Http请求)。因此,我希望authService中的isLogged()可以让我返回true / false或设置一个布尔值true / false。通常,我在Component的.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();
  }
}

1 个答案:

答案 0 :(得分:0)

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

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)
    );
}