angular - 在重试 Observable 之前更改 HTTP header

标签 angular typescript rxjs observable

我在前端使用带有 TypeScript 的 Angular 2。我正在尝试实现一个 http 拦截器,它在每个请求上设置授权 header 。如果访问 token 过期,我将尝试重试请求,在重试之前使用刷新 token 获取新的访问 token 并更改当前请求的 header 。

如何在 retryWhen 算子中更新请求头?

例如这里是 HttpInterceptor:

export class HttpInterceptor extends Http {
    get(url: string, options?: RequestOptionsArgs): Observable<Response> {
        return super.get(url, this.setRequestAuthorizationHeader(options)).retryWhen((errors: any) => this.errorHandler(errors));
    }

    private setRequestAuthorizationHeader(options?: RequestOptionsArgs): RequestOptionsArgs {
        // some checks
        // get accessToken from localStorage
        options.headers.append('Authorization', 'Bearer ' + accessToken);
    }

    private errorHandler(errors) {
        return errors.switchMap((err) => {
        if (err.status === 401) {
            let closedSubject = new Subject();

            this.authenticationService.refreshToken()
                .subscribe(data => {
                    // How to update authorization header? This doesn't work.
                    this.defaultOptions.headers.append('Authorization', 'Bearer ' + data.accessToken);

                    closedSubject.next();
                });

            return <any>closedSubject;
        }
        else {
            return Observable.throw(err.json());
        }
    });
}
}

最佳答案

我会使用 catch 而不是 retryWhen 因为后者会重播相同的可观察对象,并且参数已经设置。

顺便说一句,您的主题在 errorHanlder 中毫无用处:

export class HttpInterceptor extends Http {
  get(url: string, options ? : RequestOptionsArgs): Observable < Response > {
    return super.get(url, this.setRequestAuthorizationHeader(options)).catch(errors => this.errorHandler(errors, url, options))
  });
}

private setRequestAuthorizationHeader(options ? : RequestOptionsArgs): RequestOptionsArgs {
  // some checks
  // get accessToken from localStorage
  options.headers.append('Authorization', 'Bearer ' + accessToken);
  return options
}

private errorHandler(err: any, url: string, options ? : RequestOptionsArgs) {
  if (err.status === 401) {
    return this.authenticationService.refreshToken()
      .switchMap(data => {
          // save accessToken to localStorage
          return super.get(url, this.setRequestAuthorizationHeader(options));
      });
  }
  return Observable.throw(err.json());
}

另请注意,使用像 this.defaultOptions 这样的状态可能不是您的最佳选择,使用 anobservable 会更合适。

关于angular - 在重试 Observable 之前更改 HTTP header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43277943/

相关文章:

node.js - 如何强制 tsc 忽略 node_modules 文件夹?

javascript - RxJS 异步请求更新

rxjs - Redux Observables/RxJS : How to make epic that returns different actions based on if/else?

javascript - 为什么 RxJS 中没有调用所有订阅者

javascript - 如何处理响应对象中的错误

javascript - ngFor 中的 Angular2 组件抛出错误(viewFactory 不是函数)

angular - 每个 url 段都需要一个路由模块吗?

javascript - 根据下拉列表中选择的项目过滤 JSON API 数据

angular - 无法在 Angular 4 中监视注入(inject)服务的方法

reactjs - 升级后的 react - 懒惰 "ctor is not a function"