2016-09-22 65 views
4

我有一個昂貴的計算被一個效果調用。我現在想要確保,這個計算不會被同時調用,即如果在第一次調用仍在運行時第二次調用它,則應該忽略第二次調用。如何防止併發效果執行

我對這個問題的解決方法是創建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)); 
    } 
    }); 

with Actions.setLoading顯然是設置state.loading。然而,如果我開始計算連續2次:

store.dispatch(Actions.calculate()); 
store.dispatch(Actions.calculate()); 

輸出是

LOADING false 
LOADING false 

,因此,昂貴的計算被執行兩次。 我該如何預防?

+0

你想徹底忽略第二個動作或放入隊列嗎? –

回答

6

您可能會看到LOADING false兩次,因爲尚未執行Action.setLoading。這很可能取決於調度和操作的同步/異步。最好的是不要對此作出假設。同時

一般來說,如果你想限制了一些在同一時間執行的操作/只執行一個操作,也有一些運營商,你可以在使用rxjs V4/V5:

  1. flatMapWithMaxConcurrent | mergeMap:將同時訂閱observables的參數化最大值,保留其餘observables的緩衝區以訂閱,並在插槽變爲可用時訂閱它們。因此沒有損失。

  2. flatMapFirst | exhaustMap:只會在給定的時間訂閱一個觀察值。當前可觀測數據執行時出現的可觀測數據將丟失。當前的可觀測數據完成後,可以訂閱新的可觀測數據。

  3. concatMap:一次只能訂閱一個觀察值。將保留一個剩餘觀測量的緩衝區來訂閱,並且將在當前觀測值完成時按順序執行。因此沒有損失。

您還可以查看以下問題:Batching using RxJS?

總之,也許這樣的事情可能會爲你工作:

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

我這裏假定DO_THE_EXPENSIVE_CALCULATION()返回一個承諾(可以也是可觀察的)。