angular - HttpInterceptor 处理 401 错误不返回 Observable

标签 angular angular-http-interceptors angular-httpclient

我正在关注这个例子:https://www.intertech.com/Blog/angular-4-tutorial-handling-refresh-token-with-new-httpinterceptor/
除了方法 handle401Error 之外,一切都运行良好。它不会执行,除非我在拦截器中添加 subscribe。我一定遗漏了一些东西,即使我试图效仿那个例子。
这是相关的代码:

成分:

ngOnInit() {
  this.service.getData()
    .subscribe((response: any) => {
      this.message = `Worked with status = ${response.status}`;
    },
    error => this.message = `Failed with status = ${error.status}`);
}
服务:
constructor(private http: HttpClient) {
  this.currentToken = this.authTokenStale;
}

public authTokenStale: string = 'stale_auth_token';
public authTokenNew: string = 'new_auth_token';
public currentToken: string;

getData() {
  return this.http.get<{status}>('https://private-4002d-testerrorresponses.apiary-mock.com/getDataError401');
}

getAuthToken() {
  return this.currentToken;
}

refreshToken(): Observable<string> {
  this.currentToken = this.authTokenNew;
  return Observable.of(this.authTokenNew).delay(200);
}
拦截器:
isRefreshingToken: boolean = false;
tokenSubject: BehaviorSubject<string> = new BehaviorSubject<string>(null);

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  console.log('interceptor fired!')
  let service = this.inj.get(Service);
  // addToken() returns headers, getAuthToken() returns token
  return next.handle(this.addToken(request, service.getAuthToken())).do((event: HttpEvent<any>) => {
    if (event instanceof HttpResponse) {
      // success
    }
  }, (err: any) => {
    if (err instanceof HttpErrorResponse) {
      if (err.status === 401) {
        return this.handle401Error(request, next);
      }
    }
  });
}
句柄401错误:
handle401Error(req: HttpRequest<any>, next: HttpHandler) {
  if (!this.isRefreshingToken) {
    this.isRefreshingToken = true;
    let service = this.inj.get(Service);
    this.tokenSubject.next(null);
    return service.refreshToken()
        .switchMap((newToken: string) => {
          console.log('goes to switchMap') // does not come here!
            if (newToken) {
                this.tokenSubject.next(newToken);
                return next.handle(this.addToken(this.getNewRequest(req), newToken));
            }
            return this.logoutUser();
        })
        .catch(....)
        //.subscribe(() => {) // only works!
        .finally(() => {
          console.log('goes to finally')
            this.isRefreshingToken = false;
        });
  } else {
    return this.tokenSubject
        .filter(token => token != null)
        .take(1)
        .switchMap(token => {    
            return next.handle(this.addToken(this.getNewRequest(req), token));        
        });
  }
}
抱歉,有一些代码,但我认为所有这些都与能够重现问题有关。
我也做了一个
StackBlitz
来展示问题!

最佳答案

如果您使用 Angular 6,请记住 RxJS 库中的更改。
在新的 RxJS 中,使用 do 操作符
next.handle(req).do(() => {});
必须改为:
next.handle(req).pipe(tap(() => {}));
查看这篇文章了解更多信息:

  • https://www.academind.com/learn/javascript/rxjs-6-what-changed/
  • https://auth0.com/blog/whats-new-in-rxjs-6/
  • 关于angular - HttpInterceptor 处理 401 错误不返回 Observable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47429014/

    相关文章:

    javascript - Angular 9 中的视频 JS - 实时视频 - 'Can' 是否解决了 videojs 的问题?

    angularjs - 如何开发angularjs拦截器来控制 session

    c# - 错误: "the application completed without reading the entire request body" Angular/C#

    angular - 如何将 header 添加到我的 Angular 发布请求中?

    angular - 我想用 react 形式和 Angular Material 一次显示一个错误

    angular - 如何使用 Angular 的 2+ @angular/http 模块接收 blob 响应?

    angular - 如何使用模式验证 mat-datepicker 输入?

    angular - 为什么拦截器不返回数据给订阅者?

    angular - HttpInterceptor 重构错误信息

    angular - 从服务类进行嵌套 HTTP 调用并返回 Observable