javascript – 如何防止并发效果执行

我有一个由效果调用的昂贵计算.我现在想要确保,这个计算永远不会被同时调用,即如果在第一次调用仍在运行时第二次调用它,则应忽略第二个调用.

我解决这个问题的方法是创建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

因此,昂贵的计算执行两次.
我怎么能阻止这个?

解决方法:

您可能会看到LOADING错误两次,因为Action.setLoading尚未执行.这很可能取决于调度和操作的同步/异步.最好不要对此做出假设.

一般来说,如果要限制同时执行的操作数/一次只执行一个操作,则可以在rxjs v4 / v5中使用多个运算符:

> flatMapWithMaxConcurrent | mergeMap:将同时订阅参数化的最大可观察量,保留剩余可观察量的缓冲区以便订阅,并在插槽可用时订阅它们.因此没有损失.
> flatMapFirst | exhaustMap:只会在给定时间订阅一个可观察量.在当前可观察的执行过程中出现的可观察性丢失了.当完成当前可观察量时,可以订阅新的可观察量.
> concatMap:一次只能订阅一个观察者.将保留剩余可观察量的缓冲区以进行订阅,并且将在当前可观察量已完成时按顺序执行此操作.因此没有损失.

您还可以查看以下问题:Batching using RxJS?

总之,也许这样的事情对你有用:

@Effect()
calculate$= this.updates$
  .whenAction(CALCULATE)
  .exhaustMap(data => DO_THE_EXPENSIVE_CALCULATION())
  ;

我在这里假设DO_THE_EXPENSIVE_CALCULATION()返回一个promise(也可以是一个可观察的).

上一篇:javascript – 使用Observable进行AWS cognito回调


下一篇:javascript – Angular 4 this.http.get(…).map不是函数