Angular 拦截器根据响应路由到不同的路径

Angular Interceptor route to a different path based on response

我正在玩 Angular 拦截器,如果响应状态是 401 我想重新路由,下面是我试过的。

@Injectable()
export class AuthInterceptorService implements HttpInterceptor {

  constructor(private _localStorageService: LocalStorageService, private _router: Router, private _location: Location) { }


  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (req.url.includes("/login")) {
      return next.handle(req);
    }
    let authToken: LocalStorage = this._localStorageService.getItem('auth-token');
    if (authToken) {
      return next.handle(
        req.clone({
          headers: req.headers.append('Authorization', 'jwt ' + authToken.value)
        })
      ).pipe(tap((response: HttpResponse<any>) => {
        console.log(response);
        if (response instanceof HttpResponse) {
          if (response.body.status == 401) {
            this._router.navigate([Routes.LOGIN]);
            return response;
          }
        }
      }));
    }
    this._router.navigate(['/login']);
  }
}

这个过程正在运行,但是每当更改路由时,我都会在 chrome 开发控制台中收到此消息:错误您提供了 'undefined' 预期流的位置。您可以提供 Observable、Promise、Array 或 Iterable。

我该如何防止这种情况发生?我做错了什么?

此错误总是指缺少或错误的 return 值,在您的情况下,在某些时候,拦截方法不是 return 可观察的,而是什么都没有或其他东西。然后 Angular 在内部使用可观察对象,并且因为它不是可观察对象,所以它失败了。例如。如果你的 authToken 是未定义的,你 return 什么都没有,所以拦截方法的结果是未定义的。

谢谢@Julien 为我指明了正确的方向。查看答案后,我进行了更多挖掘以寻找解决方案,以下是对我有用的解决方案

@Injectable()
export class AuthInterceptorService implements HttpInterceptor {

  constructor(private _localStorageService: LocalStorageService, private _router: Router, private _location: Location) { }


  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (req.url.includes("/login")) {
      return next.handle(req);
    }
    let authToken: LocalStorage = this._localStorageService.getItem('auth-token');
    if (authToken) {
      return next.handle(
        req.clone({
          headers: req.headers.append('Authorization', 'jwt ' + authToken.value)
        })
      ).pipe(tap((response: HttpResponse<any>) => {
        console.log(response);
        if (response instanceof HttpResponse) {
          if (response.body.status == 401) {
            this._router.navigate([Routes.LOGIN]);
            return response;
          }
        }
      }));
    }
    this._router.navigate(['/login']);
    return empty();
  }
}

如果有人遇到这个问题,请参考:

已接受的答案没有使用 http 拦截器,但还有另一个答案使用了拦截器

我使用的解决方案只是 return 一个使用 empty()

的空观察