在我的 Ionic/Angular 應用程式中,我有一個 60 秒的可觀察計時器,它只發出與服務器時間同步的當前時間。我每分鐘獲取權限、設定等。我為每個請求傳遞一個令牌。在注銷時,我撤銷了令牌。這是我的邏輯示例。
旁注:還有一個功能,用戶可以“更改登錄型別”,例如,他們可以“成為”管理員,這個程序也可能觸發類似的情況。
this.clientTimeSub = this.timeService.clientTime
.pipe(takeUntil(this.logoutService.isLoggingOut$))
.subscribe(async (latestClientTime) => {
this.clientTime = { ...latestClientTime };
// if client time just rolled over to a new minute, update settings
if (
this.clientTime?.time?.length === 7 &&
this.clientTime?.time?.slice(-1) === '0'
) {
await updateSettings();
await updatePermissions();
// etc
// These functions will:
// (1) make an api call (using the login token!)
// (2) update app state
// (3) save to app storage
}
});
當我退出應用程式時,有一個很小的時間視窗,我可能正在發送多個 api 請求并且令牌不再有效,因為計時器在我退出時滾動到新的一分鐘,或接近它。然后我在注銷程序中看到 401: Unauthorized。
我天真的解決方案是告訴這個 observable 當一個 Subject 或 BehaviorSubject 觸發一個值告訴這個 observable 它正在注銷時停止傳播,你可以在這里看到這個.pipe(takeUntil(this.logoutService.isLoggingOut$))。
然后,在我的任何注銷方法中,我都會使用:
logout() {
this.isLoggingOut.next(true);
...
// Logout logic here, token becomes invalidated somewhere here
// then token is deleted from state, etc, navigate back to login...
...
this.isLoggingOut.next(false);
}
在注銷的那個小時間視窗中,客戶端計時器應該停止觸發并檢查它是否已滾動到新的一分鐘,以防止任何可能未經身份驗證的進一步 api 呼叫。
有沒有辦法可以輕松防止此問題發生,或者我的邏輯中是否存在可能導致此問題的缺陷?
我感謝任何幫助,謝謝!
uj5u.com熱心網友回復:
首先,這不是將 async-await 與 RXJS 一起使用的最佳方式。這是因為 RXJS 作為函式式編程的一種反應方式,有它的“管道”運算子,所以你可以“鏈接”一切。
因此,與其在訂閱回呼函式中使用計算時間的邏輯,不如使用filter () RXJ 運算子,而不是使用 await-async,您可以使用switchMap運算子,并在其中使用forkJoin或 concat 運算子。
this.timeService.clientTime
.pipe(
// Filter stream (according to your calculation)
filter((time) => {
// here is your logic to calculate if time has passed or whatever else you are doing
// const isValid = ...
return isValid;
}),
// Switch to another stream so you can call api calls
// Here with "from" we are converting promises to observables in order to be able to use magic of RXJS
switchMap(_ => forkJoin([from(updateSettings), from(updatePermissions)])),
// Take until your logout
takeUntil(this.logoutService.isLoggingOut$)
).subcribe(([updateSettings, updatePermissions]) => {
// Basically your promises should just call API services, and other logic should be here
// Here you can use
// (2) update app state
// (3) save to app storage
})
如果你像我的例子那樣拆分動作,在你的承諾中你只需呼叫 api 呼叫來更新你正在做的任何事情,然后當它完成時,在訂閱回呼中你可以更新應用程式狀態,保存到應用程式存盤等。所以你可以有 2 個場景這里:
- 來自 promise 的 Api 呼叫仍在進行中。如果您同時觸發注銷,takeUntil會執行此操作,并且您不會更新應用程式狀態等。
- 如果來自 promise 的兩個 Api 呼叫都完成了,你就在一個 subscribe 回呼塊中,如果它只是一個同步代碼(希望如此),它就會完成。然后可以執行異步代碼(您的計時器現在可以發出下一個值,這完全是關于 javascript 中的事件回圈)
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/346393.html
標籤:javascript 有角的 验证 rxjs
上一篇:JWT重繪令牌的全部意義是什么?
下一篇:Nginx入門
