如何防止并发执行
How to prevent concurrent effect execution
我有一个由效果调用的昂贵计算。我现在想确保永远不会同时调用此计算,即如果在第一次调用仍在 运行 时第二次调用它,则应忽略第二次调用。
我解决这个问题的方法是创建 2 个动作:计算和 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
因此,昂贵的计算被执行了两次。
我该如何防止这种情况?
您可能会看到 LOADING false
两次,因为 Action.setLoading
尚未执行。这很有可能取决于调度和操作的 synchrony/asynchrony。最好不要对此做出假设。
一般来说,如果您想限制同时执行的多个操作 time/execute 一次只能执行一个操作,您可以在 rxjs v4/v5 中使用许多运算符:
flatMapWithMaxConcurrent
|mergeMap
:将同时订阅参数化的最大 observables,保留剩余 observables 的缓冲区以进行订阅,并在 slot 时订阅它们变得可用。因此没有损失。
flatMapFirst
|exhaustMap
:在给定时间只会订阅一个可观察对象。当前可观察对象正在执行时出现的可观察对象将丢失。当当前的observable完成后,可以订阅新的observable。
concatMap
:一次只订阅一个可观察对象。将保留剩余可观察对象的缓冲区以供订阅,并在当前可观察对象完成时按顺序进行订阅。因此没有损失。
您还可以复习以下问题:
总而言之,也许这样的事情对您有用:
@Effect()
calculate$ = this.updates$
.whenAction(CALCULATE)
.exhaustMap(data => DO_THE_EXPENSIVE_CALCULATION())
;
我在这里假设 DO_THE_EXPENSIVE_CALCULATION()
returns 一个承诺(也可以是一个可观察的)。
我有一个由效果调用的昂贵计算。我现在想确保永远不会同时调用此计算,即如果在第一次调用仍在 运行 时第二次调用它,则应忽略第二次调用。
我解决这个问题的方法是创建 2 个动作:计算和 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
因此,昂贵的计算被执行了两次。 我该如何防止这种情况?
您可能会看到 LOADING false
两次,因为 Action.setLoading
尚未执行。这很有可能取决于调度和操作的 synchrony/asynchrony。最好不要对此做出假设。
一般来说,如果您想限制同时执行的多个操作 time/execute 一次只能执行一个操作,您可以在 rxjs v4/v5 中使用许多运算符:
flatMapWithMaxConcurrent
|mergeMap
:将同时订阅参数化的最大 observables,保留剩余 observables 的缓冲区以进行订阅,并在 slot 时订阅它们变得可用。因此没有损失。flatMapFirst
|exhaustMap
:在给定时间只会订阅一个可观察对象。当前可观察对象正在执行时出现的可观察对象将丢失。当当前的observable完成后,可以订阅新的observable。concatMap
:一次只订阅一个可观察对象。将保留剩余可观察对象的缓冲区以供订阅,并在当前可观察对象完成时按顺序进行订阅。因此没有损失。
您还可以复习以下问题:
总而言之,也许这样的事情对您有用:
@Effect()
calculate$ = this.updates$
.whenAction(CALCULATE)
.exhaustMap(data => DO_THE_EXPENSIVE_CALCULATION())
;
我在这里假设 DO_THE_EXPENSIVE_CALCULATION()
returns 一个承诺(也可以是一个可观察的)。