Угловой перехватчик не передает повторно неудачный запрос - PullRequest
0 голосов
/ 02 марта 2019

Я использую Angular 7.2 MatDialog из Angular Material и rxjs 6. После истечения срока действия токена при следующем http-запросе открывается диалоговое окно, но он не отправляет сбойный http-запрос снова.Хотя эти предложения немного отличаются от того, что мне нужно, я попробовал это и это без удачи.Все, что мне нужно, - это чтобы после закрытия диалогового окна он снова отправил неудавшийся запрос, чего не происходит в данный момент.Может ли кто-нибудь помочь найти то, что мне не хватает?

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 голосов
/ 08 апреля 2019

Я думаю, что две карты SwitchMap являются проблемой.

.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. Если это так, вы можете воспользоваться подсказкой из этого статьи и соответственно реализуйте свой вариант использования.Дайте мне знать, если вам все еще нужна помощь.

...