我有以下效果
public SetProperTab$ = createEffect(
public SetProperTab$ = createEffect(
() => {
返回 this.actions$.pipe(
ofType(actions.SetProperTab)、
switchMap((action) =>;
this.store$.select(selectors.GetHasLogicalProductInStore, { id: action.logicalProductId }).pipe(
switchMap((hasLogicalProductInStore) => {
if (hasLogicalProductInStore) {
return of(true);
} else {
return this.actions$.pipe(ofType(actions.GetLogicalProductDetailsSuccess), take(1));
}
}),
concatLatestFrom(() =>;
this.store$.select(selectors.GetProperSpecifiedLogicalProduct, { logicalProductId: action.logicalProductId })、
),
concatMap(([_, properCurrent]) => {
if (properCurrent?.ProductsLite.length) {
const lastProductConfig:RestProductLiteEntity | undefined = properCurrent.ProductsLite.at(-1);
如果 (lastProductConfig) {
this.router.navigate([`/main/product-editor/${action.logicalProductId}/product-config/${lastProductConfig.ID}`]);
}
} else {
this.router.navigate([`/main/product-editor/${action.logicalProductId}/product-config/${lastProductConfig.ID}`]);
}
返回 EMPTY;
}),
),
),
);
},
{ dispatch: false }、
);
它的基本功能是在用户点击 kendo-grid 列表后触发。然后,它会检查商店中是否已经有此类项目(及其大型数据集),如果没有,它将使用 ofType 运算符返回另一个管道,以确保 GetLogicalProductDetailsSuccess 成功完成(这发生在数据刚刚从后台下载之后),然后它将执行负责设置适当导航的逻辑......其余的并不重要。因为它正如预期的那样工作。
但在这种情况下,我不明白为什么将第一个操作符 switchMap 更改为 exasutMap 或 concatMap 会导致无法调用该效果。好吧--它被调用了,但只有一次(在选择第一个项目后),之后效果就不再有反应了,尽管下面的操作在用户点击列表项目时一直被派发......
public onSelectedChanged(value: ID | null): void {
if (value) {
this.productEditorService.onSelectedChanged(value);
this.store$.dispatch(SetProperTab({ logicalProductId: value.toString() });
}
我希望它的工作原理与 switchMap 相同......因为只在单击后执行一次操作......
問題在於你誤解了
exhaustMap
和
concatMap
在這種情況下的運作方式。讓我們來分解一下每個運算子在這裡的行為,以及為什麼
switchMap
是正確的選擇:
1.
switchMap
-
當
SetProperTab
操作被派發時,switchMap
會 訂閱 內部的 observable(在你的例子中,它是檢查商店或等待GetLogicalProductDetailsSuccess
的邏輯)。 -
如果在這個內部 observable 完成
之前
另一個
SetProperTab
操作被派發,switchMap
會 取消訂閱 先前的 observable,並使用新的logicalProductId
開始一個新的 observable。 - 這正是你想要的行為:每次點擊列表項時,你都想 取消 任何先前的導航嘗試,並根據最新的點擊開始一個新的導航。
2.
exhaustMap
-
exhaustMap
也會在第一個SetProperTab
操作時訂閱內部 observable。 -
然而,
關鍵區別
在於:如果在內部 observable 完成
之前
收到另一個
SetProperTab
操作,exhaustMap
會 忽略 新的操作。它會等到當前的內部 observable 完成後,才會處理下一個SetProperTab
操作。 -
在你的情況下,這意味著只有第一次點擊會起作用。後續的點擊會被
exhaustMap
忽略,因為它還在等待先前的導航邏輯完成。
3.
concatMap
-
concatMap
與exhaustMap
相似,它不會取消先前的 observable。 -
但是,與
exhaustMap
不同的是,concatMap
會 排隊 所有收到的SetProperTab
操作。當前一個內部 observable 完成後,它會按順序處理排隊的操作。 - 在你的情況下,這可能會導致導航到錯誤的產品配置,因為它會按照點擊的順序處理導航,而不是總是導航到最新的點擊。
結論
因為你希望每次點擊列表項時都取消先前的導航並開始新的導航,所以
switchMap
是最適合這個情境的運算子。
exhaustMap
和
concatMap
會導致你的效果無法按預期運作,因為它們會忽略或延遲後續的點擊事件。