首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为多个api调用刷新Angular 4中的标记

为多个api调用刷新Angular 4中的标记
EN

Stack Overflow用户
提问于 2018-03-14 15:25:17
回答 2查看 1.1K关注 0票数 1

我正在尝试在我的web应用程序中实现刷新令牌的概念。

在页面刷新中,我调用了4个API,当访问令牌过期时,我将调用后端,以获取基于刷新令牌的新访问令牌。

因此,在我的情况下,我能够获得新的访问令牌,但同样无法触发4个API调用,除非我手动执行页面刷新或从服务重新加载页面。但我不想在不知道最终用户的情况下重新加载页面和完成API调用。

给出一些建议或想法来做这件事。

EN

回答 2

Stack Overflow用户

发布于 2018-03-14 15:41:08

你可以使用Angular HttpInterceptor来解决你的问题。请参阅下面的代码片段。

代码语言:javascript
复制
@Injectable()
export class KgRequestInterceptorService implements HttpInterceptor {
  authenticationService: MyAuthenticationService;
  snackbarService: KgSnackbarService

  constructor(private injector: Injector) { }

  addBearerAndHeaders(req: HttpRequest<any>, token: string, overwrite?: boolean): HttpRequest<any> {
    reqHeaders = reqHeaders.set("Authorization", 'Bearer ' + token);
    return req.clone({ headers: reqHeaders });
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
    this.authenticationService = this.authenticationService ? this.authenticationService : this.injector.get<MyAuthenticationService>(MyAuthenticationService);
    return next.handle(this.addBearerAndHeaders(req, this.authenticationService.accessToken)).pipe(
      catchError((error, cought) => {
        if (error instanceof HttpErrorResponse) {
          switch ((<HttpErrorResponse>error).status) {
            case 400:
              return this.handle400Error(error);
            case 401:
              return this.handle401Error(req, next);
            case 403:
              return this.handle403Error(error);
            default:
              return _throw(error);
          }
        } else {
          return _throw(error);
        }
      })

    )
  }

  handle401Error(req: HttpRequest<any>, next: HttpHandler) {
    if (!this.isRefreshingToken) {
      this.tokenSubject.next(null);
      this.isRefreshingToken = true;
      console.log("isRefreshingToken", this.isRefreshingToken);


      // Reset here so that the following requests wait until the token
      // comes back from the refreshToken call.
      this.authenticationService = this.authenticationService ? this.authenticationService : this.injector.get<KgAuthenticationService>(KgAuthenticationService);
      this._location = this._location ? this._location : this.injector.get<Location>(Location);

      return this.authenticationService.renewToken().pipe(
        switchMap((newToken: string) => {
          if (newToken) {
            console.log("newToken Recieved:", newToken);

            this.tokenSubject.next(newToken);
            this.authenticationService.storeRenewedToken(newToken);
            return next.handle(this.addBearerAndHeaders(req, newToken, true));
          }

          // If we don't get a new token, we are in trouble so logout.
          //return this.logout();
        }),
        catchError(error => {
          // If there is an exception calling 'refreshToken', bad news so logout.
          //return this.logout();
        }),
        finalize(() => {
          this.isRefreshingToken = false;
          console.log("isRefreshingToken", this.isRefreshingToken);
        })
      );
    } else {
      return this.tokenSubject.pipe(
        filter(token => token != null),
        take(1),
        switchMap(token => {
          console.log("newtoken:", token.substr(token.length - 20, token.length - 1))
          return next.handle(this.addBearerAndHeaders(req, token, true));
        })
      )
    }
  }

  handle400Error(error) {
    if (error && error.status === 400 && error.error && error.error.error === 'invalid_grant') {
      // If we get a 400 and the error message is 'invalid_grant', the token is no longer valid so logout.
      return this.logoutUser();
    }

    return _throw(error);
  }

  handle403Error(error) {
    if (error.status === 403) { }
    return _throw(error);
  }
}

关于这一点的好文章在https://www.intertech.com/Blog/angular-4-tutorial-handling-refresh-token-with-new-httpinterceptor/

票数 2
EN

Stack Overflow用户

发布于 2018-03-14 15:35:08

在此场景中,当您有一个可观察对象并且需要从另一个请求中获取某些内容并返回另一个可观察对象时,更好的方法是使用switchMap,您可以使用SwitchMap:https://blog.angular-university.io/rxjs-switchmap-operator/

代码语言:javascript
复制
ngOnInit() {
    this._moviesDataService.getShowtimes()
        .switchMap(res => { 
            const id = Object.keys(res[0].showtimes)[0]; // assuming you have one element in your array and you want the first id from showtimes
            return this.getMovies(id); // assuming, you have a separate method that returns the movies
        })
        .subscribe(res => this.results = res)
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49271828

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档