如何在调用WS之前等待某事
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在调用WS之前等待某事相关的知识,希望对你有一定的参考价值。
我的应用使用带有令牌的SSO身份验证,该令牌可以过期。
在单击“admin”按钮时,我需要为页面的几个部分调用几个WS(这些调用没有链接)。
如果我的令牌过期,则第一次WS调用将导致401错误。然后我会要求更新令牌。我要做的是保持跟随ws呼叫,直到令牌更新完成。
我有类似的东西:
private isTokenBeingRenewed: BehaviorSubject<boolean> = new BehaviorSubject(false);
...
private handleAccessTokenExpiration(wsCall: Function, growlSuccessMsg: string, growlTitle?: string): Observable<Response> {
// flag token being renewed
this.isTokenBeingRenewed.next(true);
//start token renewal
return this.oidcSecurityService.refreshSession().flatMap(event => {
// Call WS again when token is renewed
return wsCall()
.catch(error => {
return Observable.throw(...);
})
.do((res: Response) => {
...
}, (error: any) => {
return Observable.throw(...);
})
.finally(() => {
// flag token renewal is done
this.isTokenBeingRenewed.next(false);
});
});
}
在我的Ws呼叫功能我有:
private handleWSResponse(wsCall: Function,
showGrowlSuccess: boolean,
growlTitle?: string,
growlSuccessMsg?: string): Observable<Response> {
// Avoid call renew multiple times.
return this.isTokenBeingRenewed.flatMap(isRenewing => {
// If token renewal is not in progress, calls WS
if (!isRenewing) {
// Call WS
}
}
}
问题是,当isRenewing === true时,Observable已解决,但不会返回任何内容。如果isRenewing = true,我不知道如何等待和解决?
你应该使用HttpInterceptor来实现它!
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
private authService: AuthService;
constructor(private inj: Injector) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (request.url.includes('/not-authorized')) {
return next.handle(request);
}
this.authService = this.inj.get(AuthService);
return this.authService.getRawAccessToken()
.switchMap(token => {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next.handle(request);
});
}
}
该示例与您的方案不完全匹配,但方法应该这样做。这样的事情。在这里,您必须划分必须获得授权的API。然后,您可以在auth服务中检查令牌过期。只有令牌再次有效时,“authservice”提供的Observable才应解决。然后你有一个点可以控制每个呼叫。在我看来,这是最简单的方法。此外,在这种场景中,应该使用switchMap。
如果您在这里不使用Angular,也可以使用相同的概念。只需订阅行为主题并过滤所有错误值。但是,如果您始终对第一个服务进行异步调用以检查令牌是否已过期,则您将始终丢失一些调用。您应该可以使用oidc synchronous来检查到期时间:
private isTokenBeingRenewed: BehaviorSubject<boolean> = new BehaviorSubject(false);
public handleAccessTokenExpiration(): Observable<boolean> {
this.isTokenBeingRenewed.next(true);
//start token renewal
this.oidcSecurityService.refreshSession()
.subscribe(event => this.isTokenBeingRenewed.nect(false);
return this.isTokenBeingRenewed;
}
在来电者中:
public doSth() {
handleAccessTokenExpiration
.filter(result => !result)
.switchMap(result => doWsCall())
.sunscribe();
}
如果你的电话是无法观察的。只是包裹它。
所以你要做的是,如果更新token
,立即调用wsCall
,如果没有更新token
,请调用handleAccessTokenExpiration
,然后调用wsCall
。你可以利用switchMap()
做“等待”:
private handleWSResponse(wsCall: Function,
showGrowlSuccess: boolean,
growlTitle?: string,
growlSuccessMsg?: string): Observable<Response> {
if (this.isTokenBeingRenewed) {
return wsCall();
} else {
//handle token first
//arguments here is omitted for brevity
return this.handleAccessTokenExpiration()
.switchMap(() => wsCall());
}
}
或者您可以在一个班轮中完成:
return this.isTokenBeingRenewed ? wsCall() : this.handleAccessTokenExpiration().switchMap(() => wsCall());
以上是关于如何在调用WS之前等待某事的主要内容,如果未能解决你的问题,请参考以下文章