我有一个由效果调用的昂贵计算。我现在想确保,这个计算永远不会被同时调用,即如果在第一次调用仍在运行时第二次调用它,则应忽略第二次调用。
我解决这个问题的方法是创建2个动作:calculate和setLoading。
@Effect()
calculate$ = this.updates$
.whenAction(CALCULATE)
.flatMap(data => {
console.debug('LOADING', data.state.loading);
if (!data.state.loading) {
this.store.dispatch(Actions.setLoading(true));
await DO_THE_EXPENSIVE_CALCULATION();
this.store.dispatch(Actions.setLoading(false));
}
});
使用Actions.setLoading显然设置了state.loading。但是,如果我连续开始计算2次:
store.dispatch(Actions.calculate());
store.dispatch(Actions.calculate());
输出
LOADING false
LOADING false
因此,昂贵的计算执行两次。 我该如何防止这种情况?
答案 0 :(得分:6)
您可能会看到Action.setLoading
两次,因为flatMapWithMaxConcurrent
尚未执行。这很可能取决于调度和操作的同步/异步。最好不要对此做出假设。
一般来说,如果你想限制同时执行的一些操作/一次只执行一个操作,你可以在rxjs v4 / v5中使用许多操作符:
exhaustMap
| mergeMap
:将同时订阅参数化的最大可观察量,保留剩余可观察量的缓冲区以进行订阅,并在插槽可用时订阅它们。因此没有损失。
flatMapFirst
| @Effect()
calculate$ = this.updates$
.whenAction(CALCULATE)
.exhaustMap(data => DO_THE_EXPENSIVE_CALCULATION())
;
:只会在给定时间订阅一个observable。在当前可观察的执行过程中出现的可观察性丢失了。当完成当前可观察量时,可以订阅新的可观察量。
concatMap
:一次只能订阅一个observable。将保留剩余可观察量的缓冲区以进行订阅,并且将在当前可观察量已完成时按顺序执行此操作。因此没有损失。
您还可以查看以下问题:Batching using RxJS?
总之,也许这样的事情对你有用:
DO_THE_EXPENSIVE_CALCULATION()
我在这里假设customer/account/create
返回一个承诺(也可以是一个可观察的承诺)。