角拦截器不重新提交失败的请求

时间:2019-03-02 02:59:26

标签: angular rxjs modal-dialog angular-material

我正在使用Angular Material和rxjs 6中的Angular 7.2 MatDialog。令牌过期后,在下一个http请求上,它将弹出对话框,但不会再次提交失败的http请求。 尽管这些建议与我所需的建议略有不同,但我尝试thisthis时并不走运。 我所需要的是,在对话框关闭后,它再次提交失败的请求,目前还没有发生。 有人可以协助找到我所缺少的吗?

private refreshingToken: boolean = false;

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    return next.handle(this.setAuthorizationHeader(request))
        .pipe(
            catchError((error, caught) => {
                if (error instanceof HttpErrorResponse) {
                    if (error.status == 401) {
                        if (this.refreshingToken) {
                            return empty();
                        } else {
                            this.refreshingToken = true;
                            setTimeout(() => {
                                const dialog = this.authenticationService.OpenLoginDialog();
                                if (dialog) {
                                    const afterClosed$: Subscription = dialog
                                        .afterClosed()
                                        .pipe(
                                            switchMap(() => {
                                                return this.store.select(state => state.AccountState)
                                                .pipe(
                                                    map(data => data.accountLoggedIn)
                                                )
                                            }),
                                            switchMap((accountLoggedIn: boolean) => {
                                                if (accountLoggedIn) {
                                                    return next.handle(this.setAuthorizationHeader(request));
                                                }
                                            }),
                                            finalize(() => {
                                                this.refreshingToken = false;
                                                if (afterClosed$)
                                                afterClosed$.unsubscribe();
                                            })
                                        )
                                        .subscribe(afterClosedsubscribe => {
                                            console.log({afterClosedsubscribe: afterClosedsubscribe});
                                        });
                                }
                            });
                        }

                    }
                }
                return caught;
            })
        );
}

private setAuthorizationHeader(request: HttpRequest<any>): HttpRequest<any> {
    const token = this.tokenService.Get();
    if (token != null) {
        request = request.clone({
            setHeaders: {
                Authorization: `${token.tokenType} ${token.accessToken}`
            }
        });
    }
    return request;
}

1 个答案:

答案 0 :(得分:0)

我认为这是两个switchMaps。

.pipe(
   switchMap(() => {
     return this.store.select(state => state.AccountState)
            .pipe(map(data => data.accountLoggedIn))
   }),
   switchMap((accountLoggedIn: boolean) => {
     if (accountLoggedIn) {
       return next.handle(this.setAuthorizationHeader(request));
     }
   }),
   finalize(() => {
     this.refreshingToken = false;
     if (afterClosed$)
        afterClosed$.unsubscribe();
   })
 )

以此替换上面的代码。

.pipe(
   tap(() => {
     this.store.select(state => state.AccountState)
       .pipe(
         switchMap((data) => {
            if (data.accountLoggedIn) {
               return next.handle(this.setAuthorizationHeader(request));
            }
         }),
         finalize(() => {
           this.refreshingToken = false;
           if (afterClosed$)
              afterClosed$.unsubscribe();
         })
       );
   })
)

顺便说一句,请注意。您执行此过程的方式将永远不会执行原始HTTP请求的订阅。您正在拦截器中使用setTimeout。因此,它不会返回到原始请求者。拦截器只要到达setTimeout就将结束。

如果我对它的理解正确,那么您正在尝试在存在401时恢复会话。如果是这种情况,则可以从此article中获取线索并相应地实现用例。让我知道您是否仍然需要帮助。