我有一個observable監聽路由變化的 :) 我也有一個promise可以清除我的本地存盤,當它完成后我立即改變了路由,但是switchMap/switchMapTo我的路由變化 observable 內部得到了舊值..為什么會發生這種情況?
我已經嘗試了很多方法來解決這個問題——我找到了兩個可行的方法 :) 但我想了解它們為什么有效。有人可以幫忙嗎?這是關于hot/cold observables問題的嗎?也許與event loop? 我真的不知道:)
this.storageService.clear().then((_) => {
// this was successful!! And it was checked - user is deleted :)
// now change the route and trigger the observable below :)
});
this.router.events.pipe(
filter((e: Event): e is NavigationEnd => e instanceof NavigationEnd)
/*
switchMap in here to get the user!
Options 1 2 show that the user info exists!!
Although I know for sure that it was deleted.
Option 3 4 work.
*/
// 1) switchMapTo(from(this.storageService.getAsync<IUser>('user'))),
// 2) switchMapTo(this.storageService.getAsync<IUser>('user')),
// 3) switchMap(async (_) => {
// const y = await this.storageService.getAsync<IUser>('user');
// return y;
// }),
// 4) switchMapTo(defer(() => this.storageService.getAsync<IUser>('user'))),
);
// Question edited for extra information - this is the getAsync function
async getAsync<T>(key: string) {
const result: GetResult = await Storage.get({ key });
return JSON.parse(result.value) as T;
}
uj5u.com熱心網友回復:
急切與懶惰執行
發生這種情況是因為 Promise 是急切的,而 observable 是懶惰的。也就是說,一個 observable 在訂閱之前不會做任何事情,而 Promise 從它被定義的那一刻起就會嘗試解決它自己。
為了以最直接的方式解決這個問題,我將如何撰寫它:
this.router.events.pipe(
filter((e: Event): e is NavigationEnd => e instanceof NavigationEnd),
switchMap(_ => this.storageService.getAsync<IUser>('user'))
);
更新:
當然,不僅異步代碼(如 promises 和 observables)可以具有急切/惰性求值語意。常規同步代碼可能有相同的問題。由于在同步背景關系中可能更容易理解問題,因此我將在下面創建一些示例來探索這一點,而無需使用 Promise 或 observables。
考慮這個不可觀察的代碼:
在第一個示例中,我們有一個函式addNumbers可以為您完成兩個數字相加的作業。它是急切的,所以它會立即完成作業,然后在呼叫后回傳一個值。您可以看到,在第 5 行,c()將等于 8。3并5在第 6 行相加,然后在第 8 行列印
function addNumbers(a, b){
const answer = a b;
return () => answer;
}
const c = addNumbers(3, 5);
console.log("This should be an 8:", c());
在下一個例子中,我們有一個非常相似的函式,但它是惰性的。它記住你給它的數字,但它實際上并沒有添加數字,直到有東西呼叫它。在這種情況下,c需要c()在3和5以任何方式實際使用之前呼叫。5并且3直到第 7 行才加在一起。
function addNumbers(a, b){
return () => a b;
}
const c = addNumbers(3, 5);
console.log("This should be an 8:", c());
懶惰與急切的后果
考慮這兩個例子。如果您了解他們為什么列印不同的值,您就會了解手頭的問題:)
示例 1:
const a = { n: 3 };
const b = { n: 5 };
function addNumbers(v1, v2) {
const answer = { n: v1.n v2.n };
return () => answer;
}
const c = addNumbers(a, b);
a.n = 7;
console.log('Eager Evaluation:', c());
在這里,c.n等于3 5因為c之前a.n被評估過被設定為7。這與您在洗掉用戶之前檢索用戶時的情況相同。它沒有看到用戶資訊在此期間發生了變化,因為已經計算了該值。
Example 2:
const a = { n: 3 };
const b = { n: 5 };
function addNumbers(v1, v2) {
return () => ({ n: v1.n v2.n });
}
const c = addNumbers(a, b);
a.n = 7;
console.log('Lazy Evaluation:', c());
Here, c.n is equal to 7 5 because c was evaluated after a.n was set to 7. This is the same as when you retrieved the user using defer. This time we check the value of a.n the moment that c() is evaluated, not when addNumbers(v1, v2) is evaluated.
See the difference?
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/317055.html
