CanDeactivate中的可观察处理

时间:2019-07-03 07:40:23

标签: angular

我有一个拦截器,可以在令牌过期时捕获服务器错误。然后,拦截器向api请求刷新的令牌。成功后,拦截器将再次发送http请求。发生错误时,拦截器会删除本地存储,并应重定向到登录页面。

现在我有一个带有canDeactivate Guard的页面。所以我想签入canDeactivate Guard令牌是否有效。如果无效,我想向API请求刷新的令牌。成功后,我不想离开页面。发生错误时,我要注销用户并重定向到登录页面。

// canDeactivateGuard
export interface CanComponentDeactivate {
  canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}

@Injectable({
  providedIn: 'root',
})
export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactivate> {
  canDeactivate(component: CanComponentDeactivate) {
    return component.canDeactivate ? component.canDeactivate() : true;
  }
}
// component
canDeactivate(): Observable<boolean> | boolean {
    if (!this.authService.isTokenValid()) {
      // here i want to ask the api for a new token
      // on error of api I want to redirect the user to login page
      // and don't want to show a modal
      return this.authService.refreshToken().pipe(
        map(res => {
          console.log('test');
          return false;
        }),
        catchError(err => {
          console.log('test error');
          return of(true);
        })
      );
    }
    if (Object.is(this.testForm.get('text').value, this.oldText)) {
      this.modalService.hide(1);
      return true;
    } else {
      this.modalRef = this.modalService.show(this.modalTemplate);
      return false;
    }
  }
// AuthService
 public refreshToken(): Observable<Token> {
    return this.http.post<{ data: any }>(`${environment.apiUrl}/auth/refresh`, {}).pipe(
      map(({ data }): any => {
        const apiToken = this.tokenAdapter.adapt(data);
        this.setJwtToken(apiToken);
        this.currentTokenSubject.next(apiToken);
        return apiToken;
      })
    );
  }

我不知道如何更改从api捕获错误的代码,以及如何重定向用户。 canDeactivate方法的map()和catchError()中的console.logs都不会被调用。

1 个答案:

答案 0 :(得分:0)

refreshToken应该遵循以下格式,这将很有帮助

    return this.http.get(`${environment.apiUrl}/auth/refresh`, {
    }).pipe(
      map(({ data }): any => {
        const apiToken = this.tokenAdapter.adapt(data);
        this.setJwtToken(apiToken);
        this.currentTokenSubject.next(apiToken);
        return apiToken;
      }),
      catchError(() => {
      return of(false);
    }));

然后使用canDeactivate方法

// component
canDeactivate(): Observable<boolean> | boolean {
  if(!this.authService.isTokenValid()) {
  // here i want to ask the api for a new token
  // on error of api I want to redirect the user to login page
  // and don't want to show a modal
  return this.authService.refreshToken().pipe(
    map(res => {
      if (!res) {
        console.log('test error');
        return true;
      }

      console.log('test');
      return false;
    })
  );
}
if (Object.is(this.testForm.get('text').value, this.oldText)) {
  this.modalService.hide(1);
  return true;
} else {
  this.modalRef = this.modalService.show(this.modalTemplate);
  return false;
}
    }