在Angular 7 http拦截器中选择右RxJs运算符

问题描述 投票:0回答:1

我是RxJ的新手,如果您能建议我可以在拦截器中使用哪个运算符,我将不胜感激。如果会话即将结束,我需要执行异步请求以刷新身份验证令牌:

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    return next.handle(req)
        .pipe(
            //catchError operator works good, everything's ok here
            catchError((error: HttpErrorResponse) => {
                if (error instanceof HttpErrorResponse) {
                    let refreshToken = localStorage.getItem("refreshToken");

                    if (error && error.status === 401 && refreshToken) {
                        // 401 errors are most likely going to be because we have an expired token that we need to refresh.
                        if (this.refreshTokenInProgress) {
                            // If refreshTokenInProgress is true, we will wait until refreshTokenSubject has a non-null value
                            // which means the new token is ready and we can retry the request again
                            return this.refreshTokenSubject.pipe(
                                filter(result => result !== null),
                                take(1),
                                switchMap(() => next.handle(this.authRequest(req)))
                            );
                        }
                        else {
                            this.refreshTokenInProgress = true;
                            // Set the refreshTokenSubject to null so that subsequent API calls will wait until the new token has been retrieved
                            this.refreshTokenSubject.next(null);

                            return this.backend.auth.refreshToken().pipe(
                                switchMap((res) => {
                                    if (res) {
                                        //...
                                        return next.handle(this.authRequest(req));
                                    }
                                    else {
                                        this.backend.auth.logOut();
                                        window.location.reload();
                                    }

                                }),
                                // When the call to refreshToken completes we reset the refreshTokenInProgress to false
                                // for the next time the token needs to be refreshed
                                finalize(() => this.refreshTokenInProgress = false)
                            );
                        }
                    }
                    else {
                        this.refreshTokenInProgress = false;
                       //...                            
                        return throwError(error.error);
                    }

                }
            }),
            //The problem is here, I'm not sure which operator to use to handle successfull response
            tap(event => {
                if (event instanceof HttpResponse) {
                    if ((this.backend.auth.getAccessCookieExpireDate())) {
                        let diffMin = 0;
                        let diffMs = (Date.parse(this.backend.auth.getAccessCookieExpireDate()) - Date.parse(new Date().toUTCString()));
                        diffMin = Math.round(((diffMs % 86400000) % 3600000) / 60000);
                        if (diffMin <= 10) {
                            //refresh token automatically before it dies
                            let refreshToken = localStorage.getItem("refreshToken");
                            if (refreshToken) {
                                //this async request is not called, can't see it in network
                                this.backend.auth.refreshToken().pipe(
                                    tap((res) => {
                                        if (res) {
                                            //...
                                        }
                                        else {
                                            this.backend.auth.logOut();
                                            window.location.reload();
                                        }
                                    })
                                );

                            }
                        }
                    }  
                }
            })
        );
}

所以问题出在第二个运算符函数tap()中,它很适合我,因为我不需要返回observable,但是它不允许我执行异步请求。

javascript rxjs angular6 angular7
1个回答
0
投票

您可以将switchMap用于可观察对象,并将map用于最后的传入事件。

switchMap(event => {
  if (event instanceof HttpResponse) {
    //...
    return this.backend.auth.refreshToken().pipe(
      map(res => {
        //...
        return event;
      })
    );
  }
  return of(event);
}) 
© www.soinside.com 2019 - 2024. All rights reserved.