有人可以解释一下拦截器如何通过提供程序捕获错误功能吗?

时间:2019-02-24 13:04:47

标签: angular ionic3 angular-http-interceptors

我已经在控制错误状态的地方实现了拦截器,并且对于应该在哪里捕捉错误或应该使用什么感到困惑:.of,throw或empty?

 intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (!req.url.includes('auth')) {
      console.log("NO INCLUDE auth ")
      let getTsObs = Observable.fromPromise(this.storage.get('token'));
      const tokenObservable = getTsObs.map(token => {
        return req = req.clone({
          setHeaders: {
            Authorization: `Bearer ${token}`
          }
        });
      });
      return tokenObservable.flatMap((req) => {
        return next.handle(req)
          .do((event: HttpEvent<any>) => {
            if (event instanceof HttpResponse) {
              // do stuff to the response here
            }
          }, error => {
            if (error.status === 403) {
              this.cleanApp();                  
              return Observable.throw(error);
            }
            else if(error.status === 404 ||error.status === 500){
              return Observable.of([]);
            }else {                
              return Observable.throw(error);                  
            }
          })
      })
    }
    else {
      console.log("INCLUDE auth")
      let clone = req.clone({
        setHeaders: {
          Accept: `application/json`,
          'Content-Type': `application/json`
        }
      });
      return next.handle(clone);
    }
  }

 private cleanApp() {  
    this._us.removeStorageTokenExpired();
    let nav = this.app.getActiveNav();
    nav.setRoot('Login');  
  }

我想在错误为403时发送给Login并取消下一个调用,例如,如果我使用forkjoin。

我的后端返回错误404和500,结果为[],当此调用不返回任何内容时,但是我不知道这是否是最好的返回方法,以防调用正常但不返回任何行。出于这个原因,例如,您可以看到我的代码向其返回Observable.of([])不会取消forkjoins。

现在我的提供者是:

public listGroups(action, search, page): Observable<any> {
    let url = URL_SERVICIOS + '/users/groups?action=' + action;
    if (action === "all") {
      url = url + '&search=' + search + '&page=' + page;
    }
    return this.http
      .get(url)
      .map(res => {
        if (action === "all") {
          return res;
        } else {
          return res['result'];
        }
      })
      .catch(error => {
        //if (error.status === 404||error.status===500)
          //return Observable.of([]);
        return Observable.of([]); 
      })
  }

第一次,当我取消注释前两行时,出现此错误:

错误TypeError:您在期望流的位置提供了“ undefined”。您可以提供一个Observable,Promise,Array或Iterable。

我已经解决了这个错误,并在第一行的第二行添加了注释。

有人可以解释一下正确处理拦截器和提供程序错误的最佳方法是什么?

另一方面,当错误为403时,我有一个cleanApp来清理存储,但是如果我有3次调用的forkjoin,它将被调用3次,并且会发生错误。我怎样才能做到那只做1次呢?

谢谢

1 个答案:

答案 0 :(得分:0)

我将简化拦截器,并使用Guard服务处理错误。另外,我将避免从本地存储请求令牌。我会存储它,将它传递到内存中,然后在AuthService中检索它。

@Injectable()
export class TokenInterceptor implements HttpInterceptor {
  constructor(public _auth: AuthService) {}
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (this.auth.authToken) {
      console.log('JWT', this.auth.authToken)
      request = request.clone({
        setHeaders: {
          Authorization: `Bearer ${this.auth.authToken}`,
        },
      })
    }
    return next.handle(request)
  }
}

将此作为提供程序放置在您的app.module中

    {
      provide: HTTP_INTERCEPTORS,
      useClass: TokenInterceptor,
      multi: true,
    },
@Injectable()
export class AuthGuard implements CanActivate {
  constructor(
    private _router: Router,
    private _auth: AuthService
  ) {}
  canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean> | boolean {
    const token = auth.authToken
    if (!token) {
      // Session Expired
      this._router.navigate(['/login'])
    }
    return true
  }
}

  {
    path: '',
    canActivate: [AuthGuard],
    component: LayoutMainComponent
  },
@Injectable()
export class AuthService {
  currentUser$: BehaviorSubject<any> = new BehaviorSubject<any>(null)

  public authToken: String

  constructor() {
    // save auth token
    this.currentUser$.pipe(filter(user => !!user)).subscribe(user => {
      this.authToken = user.token
    })