javascript - 在 Angular 7 http 拦截器中选择正确的 RxJs 运算符
问题描述
我是 RxJs 的新手,如果您能建议我可以在拦截器中使用哪个运算符,我将不胜感激。如果会话即将结束,我需要执行异步请求以刷新身份验证令牌:
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,但它不允许我执行异步请求。
解决方案
您可以在最后使用switchMap
Observable 和map
传入事件。
switchMap(event => {
if (event instanceof HttpResponse) {
//...
return this.backend.auth.refreshToken().pipe(
map(res => {
//...
return event;
})
);
}
return of(event);
})
推荐阅读
- amazon-web-services - 在 Cognito 或 AppSync 中存储用户属性?
- java - 命令提示符中的不兼容类型错误
- html - Sass:将相同的规则应用于两个类以确保 span 元素的背景颜色不会改变
- apache-spark - 在 Databricks 上将 spark.databricks.service.server.enabled 设置为 true 时会发生什么?
- java - 如何从这个 Json 获取消息
- javascript - 重新渲染时反应自定义挂钩状态未更新
- openedx - 什么是打开 Edx 中的 raise Exception("Can't fetch setting of a disabled backend/provider.")?
- flutter - 如何从 for 循环中返回一个小部件,其中包含颤动的 json 数据?
- android - 定义接口时如何保持 Kotlin 属性语法?
- java - 如何找到重叠区域?