Может кто-нибудь объяснить мне, как перехватчик ловит функцию ошибки с провайдерами? - PullRequest
0 голосов
/ 24 февраля 2019

Я реализовал свой перехватчик, где я контролирую состояние ошибки, и меня смущает вопрос, где я должен ловить ошибки или что я должен использовать: .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 и отменить следующие вызовы, например, если я использую 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([]); 
      })
  }

В первый раз,когда я раскомментировал 2 первые строки, я получаю эту ошибку:

ОШИБКА TypeError: Вы указали 'undefined', где ожидался поток.Вы можете предоставить Observable, Promise, Array или Iterable.

Я исправил эту ошибку, комментируя 2 первые строки.

Может кто-нибудь объяснить мне, как лучше всего обрабатывать ошибкус перехватчиком и провайдерами правильно?

С другой стороны, у меня есть cleanApp для очистки хранилища, когда ошибка 403, но если у меня есть forkjoin с 3 вызовами, он будет вызываться 3 раза, и это произойдетошибка.Как я могу добиться этого, чтобы сделать это только 1 раз.

Спасибо

1 Ответ

0 голосов
/ 24 февраля 2019

Я бы упростил перехватчик и обработал бы ошибки с помощью службы охраны.Кроме того, я бы не стал запрашивать токен из локального хранилища.Я бы сохранил его, передал в память и получил в рамках службы 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)
  }
}

Поместите это в качестве поставщика в ваше приложение. Модуль

    {
      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
    })
...