[英]Awaiting the value of a promise without using the async await keywords?
在我的 Angular HttpInterceptor class 中,我正在實現一種刷新機制,用於檢測 JWT 令牌何時過期,並從后端檢索一個新的令牌。 一旦檢索到新的令牌,它將覆蓋本地存儲中的令牌,從而延長用戶 session 的到期時間。
HttpInterceptor 的 function 的一部分是如果檢測到 JWT 到期日期已到,則將用戶從其 session 中注銷。
但是我遇到了一個問題。 在發出對 JWT 的請求后,似乎馬上又向后端發送了另一個請求。 由於此時令牌已過期,因此 API 返回 403,並且攔截器正在檢測到這一點並將用戶踢出 session,然后新的 Z1D1FADBD9150349C135781140F 令牌的響應已返回。 這意味着用戶在令牌有機會刷新之前被注銷。
通常這不是問題,因為我可以使用 async/await 來確保在發出任何其他請求之前返回新的 JWT。 但是,這在攔截器中不起作用,因為它實現了HttpInterceptor
接口,這意味着如果我嘗試在接口實現的intercept
方法上使用async
關鍵字,那么我會得到一個編譯器錯誤,因為intercept
方法的返回類型必須是Observable<HttpEvent<T>>
並且不能是Promise<Observable<HttpEvent<T>>>
。
//The below violates the HttpInterceptor interface
async intercept(
req: HttpRequest<any>,
next: HttpHandler
): Promise<Observable<HttpEvent<any>>> { ... }
//The below violates the async keyword
async intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> { ... }
我當前的攔截方法代碼如下。
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
req = this.addHeaders(req);
if(req.headers.has("refreshTokenRequest")) {
return next.handle(req).pipe(tap(val => console.log("Interceptor handler, req to: " + req.url)));
}
if(localStorage.getItem("jwt_token")) {
if(util.isJwtExpired("jwt_token")) {
console.log("Jwt is expired, getting new token");
this.getNewToken().then(newTokenResponse => { //the .then() method needs to be awaited so that the expired JWT token can be overwritten before ANY other requests are sent
this._authService.setAuthorizationToken(newTokenResponse.token);
console.log("New token set");
return this.handleRequestWithCatchError(req, next);
});
}
}
return this.handleRequestWithCatchError(req, next);
}
因此,我需要一種方法來等待 this.getNewToken this.getNewToken()
promise 的返回值,而不使用 async/await 關鍵字。 有沒有辦法做到這一點?
您可以從 promise 創建一個 observable,並使用mergeMap
運算符合並您要返回的 observable。
import { from } from 'rxjs';
import { tap, mergeMap } from 'rxjs/operators';
...
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
req = this.addHeaders(req);
if(req.headers.has("refreshTokenRequest")) {
return next.handle(req).pipe(tap(val => console.log("Interceptor handler, req to: " + req.url)));
}
if(localStorage.getItem("jwt_token")) {
if(util.isJwtExpired("jwt_token")) {
console.log("Jwt is expired, getting new token");
return from(this.getNewToken.call(this)).pipe(
tap(newTokenResponse => {
this._authService.setAuthorizationToken(newTokenResponse.token)
}),
mergeMap(() => this.handleRequestWithCatchError(req, next))
)
}
}
return this.handleRequestWithCatchError(req, next);
}
你不應該使用 Promise,而應該使用 observables。
無論如何,只需將它包裹在一個 promise 上,您在加載數據時解決該問題。
req = this.addHeaders(req);
const prom = new Promise((resolve, reject) => {
if(req.headers.has("refreshTokenRequest")) {
// Your code here
}
})
return prom.then(v => this.handleRequestWithCatchError(req, next));
正如@mbojko指出的那樣,返回一個可觀察對象(就像我首先說的那樣),因為簽名不接受承諾。
return from(prom.then(v => this.handleRequestWithCatchError(req, next)));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.