每次出现 401 以外的错误时,我都必须重试 5 次并获取刷新令牌。我正在使用下面的代码,它以无限循环结束
服务实现:
@Injectable()
export class ApiService {
public authenticate(
credentials: Credentials,
accessCode: string): Observable<Auth> {
const requestBody: Record<string, any> = { credentials, access_code: accessCode};
return this.http.post<Auth>(this.credentialsAuthUrl, requestBody).pipe(
map((res: Auth) => {
const auth = new Auth(res);
if (!this.validateJwtToken(accessCode, auth)) {
throw Error('invalid_token');
}
sessionStorage.setItem('accessToken', auth.accessToken);
sessionStorage.setItem('refreshToken', auth.refreshToken);
localStorage.setItem('some-accessToken', auth.accessToken);
return auth;
})
);
}
}
拦截器:
Injectable()
export class CustomInterceptor implements HttpInterceptor {
public constructor(private apiService: ApiService) {}
public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(
retryWhen((error) =>
error.pipe(
retryWhen(this.genericRetryStrategy()),
catchError((err) => of(err))
)
)
);
}
}
重试逻辑:
private genericRetryStrategy = ({
maxRetryAttempts = 5,
scalingDuration = 1000,
excludedStatusCodes = [ 401 ]
}: {
maxRetryAttempts?: number;
scalingDuration?: number;
excludedStatusCodes?: number[];
} = { }) => (attempts: Observable<any>) => {
return attempts.pipe(
mergeMap((error, i) => {
const retryAttempt = i + 1;
if (
retryAttempt > maxRetryAttempts ||
excludedStatusCodes.find((e) => e === error.status)
) {
return throwError(error);
}
console.log(
`Attempt ${retryAttempt}: retrying in ${retryAttempt }ms`
);
return forkJoin(
this.apiService.authenticate(
credentials,
localStorage.getItem('accessCode')),
timer(scalingDuration)
);
}),
finalize(() => console.log('We are done!'))
);
}
}
参考链接:https://www.learnrxjs.io/learn-rxjs/operators/error_handling/retrywhen