RXJS/Angular 替换 Observable
RXJS/Angular Replace Observable
在 angular 拦截器中,我想检查是否存在 auth-token。如果不是,应该刷新,重新发送请求。
return next.handle(authReq).pipe(map((result: any) => {
if (result.body && result.body.error) {
if (result.body.error === 'ERR_TOKEN_EXPIRED' || result.body.error === 'ERR_TOKENS_DO_NOT_MATCH') {
console.log('Token is expired or invalid, refreshing.', result.body.error);
return this.userService.refreshLoginToken().subscribe(success => {
if (success) {
return this.intercept(req, next);
}
});
}
}
return result;
}));
问题是我不知道如何用新的 next.handle() 替换原来的 Observable returned。 this.userService.refreshLoginToken().subscribe()
return 之前的 return 语句是一个订阅对象。如果我只是通过管道传输 refreshLoginToken()
的结果,它将无法工作,因为 refreshLoginToken 发送一个仅在有订阅时才执行的 httprequest。
要将问题简化为一行:
我怎样才能用 return 由 this.intercept(req, next)
编辑的 return 替换第 1 行中由 next.handle() 编辑的 Observable?
谢谢!
我认为你应该以不同的方式来做。
请检查下面的示例和最新的 switchMap
:
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {StoreState} from '@core/store';
import {select, Store} from '@ngrx/store';
import {getAuthToken} from '@v2/core/store/auth/auth.reducer';
import {iif, Observable, of} from 'rxjs';
import {switchMap, take} from 'rxjs/operators';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(protected readonly store: Store<StoreState>) {}
public intercept(request: HttpRequest<void>, next: HttpHandler): Observable<HttpEvent<void>> {
return this.store.pipe(
select(getAuthToken),
take(1),
switchMap(token =>
iif(
() => !token,
of(request),
of(
request.clone({
setHeaders: {
Authorization: `Bearer ${token?.accessToken}`,
},
}),
),
),
),
switchMap(clonedRequest => next.handle(clonedRequest)),
);
}
}
在 angular 拦截器中,我想检查是否存在 auth-token。如果不是,应该刷新,重新发送请求。
return next.handle(authReq).pipe(map((result: any) => {
if (result.body && result.body.error) {
if (result.body.error === 'ERR_TOKEN_EXPIRED' || result.body.error === 'ERR_TOKENS_DO_NOT_MATCH') {
console.log('Token is expired or invalid, refreshing.', result.body.error);
return this.userService.refreshLoginToken().subscribe(success => {
if (success) {
return this.intercept(req, next);
}
});
}
}
return result;
}));
问题是我不知道如何用新的 next.handle() 替换原来的 Observable returned。 this.userService.refreshLoginToken().subscribe()
return 之前的 return 语句是一个订阅对象。如果我只是通过管道传输 refreshLoginToken()
的结果,它将无法工作,因为 refreshLoginToken 发送一个仅在有订阅时才执行的 httprequest。
要将问题简化为一行:
我怎样才能用 return 由 this.intercept(req, next)
编辑的 return 替换第 1 行中由 next.handle() 编辑的 Observable?
谢谢!
我认为你应该以不同的方式来做。
请检查下面的示例和最新的 switchMap
:
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {StoreState} from '@core/store';
import {select, Store} from '@ngrx/store';
import {getAuthToken} from '@v2/core/store/auth/auth.reducer';
import {iif, Observable, of} from 'rxjs';
import {switchMap, take} from 'rxjs/operators';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(protected readonly store: Store<StoreState>) {}
public intercept(request: HttpRequest<void>, next: HttpHandler): Observable<HttpEvent<void>> {
return this.store.pipe(
select(getAuthToken),
take(1),
switchMap(token =>
iif(
() => !token,
of(request),
of(
request.clone({
setHeaders: {
Authorization: `Bearer ${token?.accessToken}`,
},
}),
),
),
),
switchMap(clonedRequest => next.handle(clonedRequest)),
);
}
}