2017-07-07 8 views
2

RxJSに慣れようとしていて、角度2+とRxJSが新しくなりました。ナビゲーションを表示ローダースピナーと角度2の遅れ+

私はルートの移行にかかる負荷スピナーを示したが、それはある程度の時間、より多くを要する場合にのみ、ラッツは160msで
を言って、私は店をngrxするサブスクリプションに、別の成分として、負荷スピナーを持っているので、私は/非表示の負荷を示し、私のアプリのルートコンポーネントで痛みの値に基づいてスピナー(showSpinner)

、私は変更イベントをルータにサブスクライブ、およびディスパッチアクション(SHOW_SPINNER/HIDE_SPINNER)
そこで質問があり、それを達成するための簡単な方法はあります?ここで

は、私のコードの一部

.... 

export const navigationStreamForSpinnerStatuses = { 
    NAVIGATION_STARTED: 'NAVIGATION_STARTED', 
    NAVIGATION_IN_PROGRESS: 'NAVIGATION_IN_PROGRESS', 
    NAVIGATION_ENDED: 'NAVIGATION_ENDED' 
}; 

です....

private navigationStartStream; 
private navigationStartStreamWithDelay; 
private navigationFinishStream; 

constructor(private store: Store<IAppState>, private router: Router) { 
    this.navigationStartStream = router.events 
    .filter(event => { 
     return event instanceof NavigationStart; 
    }) 
    .map(() => navigationStreamForSpinnerStatuses.NAVIGATION_STARTED); 

    this.navigationStartStreamWithDelay = this.navigationStartStream 
    .delay(160) 
    .map(() => navigationStreamForSpinnerStatuses.NAVIGATION_IN_PROGRESS); 

    this.navigationFinishStream = router.events 
    .filter(event => { 
     return event instanceof NavigationEnd || event instanceof NavigationCancel || event instanceof NavigationError; 
    }) 
    .map(() => navigationStreamForSpinnerStatuses.NAVIGATION_ENDED); 

    this.navigationStartStream 
    .merge(this.navigationFinishStream) 
    .merge(this.navigationStartStreamWithDelay) 
    .pairwise() 
    .subscribe([previousStatus, currentStatus] => { 
     if (previousStatus !== navigationStreamForSpinnerStatuses.NAVIGATION_ENDED && currentStatus === navigationStreamForSpinnerStatuses.NAVIGATION_IN_PROGRESS) { 
     this.store.dispatch({ type: StateLoaderSpinnerActionsTypes.SHOW_SPINNER }); 
     } else if (previousStatus === navigationStreamForSpinnerStatuses.NAVIGATION_IN_PROGRESS && currentStatus === navigationStreamForSpinnerStatuses.NAVIGATION_ENDED) { 
     this.store.dispatch({ type: StateLoaderSpinnerActionsTypes.HIDE_SPINNER }); 
     } 
    }); 
} 

答えて

0

それは時間の前に返した場合、あなたのスピナータイマーをキャンセルするtakeUntilオペレータを利用しています。さらに、timerを使用して一定の時間が経過した後にアクションをトリガーするホット観測可能オブジェクトを作成します。

takeUntilソースの観測可能なシーケンスから他の観測可能なシーケンスまたはプロミスが値を生成するまで値を返します。

https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/takeuntil.md

timer dueTimeが経過した後、各期間の後た後の値を生成する観察シーケンスを返します。

https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/timer.md

あなたは、各ストリームに直接派遣を処理することにより、ここにあなたのロジックを簡素化することができます。

this.navigationEnd$ = router.events 
    .filter(event => event instanceof NavigationEnd || event instanceof NavigationCancel || event instanceof NavigationError); 

this.navigationStart$ = router.events 
    .filter(event => event instanceof NavigationStart) 
    .subscribe(_ => { 
    Observable.timer(160) 
     .takeUntil(this.navigationEnd$) 
     .subscribe(_ => this.store.dispatch({ type: StateLoaderSpinnerActionsTypes.SHOW_SPINNER }); 
    }); 

this.navigationEnd$.subscribe(_ => this.store.dispatch({ type: StateLoaderSpinnerActionsTypes.HIDE_SPINNER }); 

それでは、私たちがやったことは、ナビゲーションの開始に耳を傾け、160msでのためtimerを開始しています。ナビゲーション終了イベントがタイマーの前に発生した場合、スピナーは表示されません(takeUntil)。それ以外の場合は、ストアアクションがディスパッチされ、スピナーが表示されます。スピナーが表示されているかどうかにかかわらず、ナビゲーションが終了した後、私たちは非表示のスピナーアクションをディスパッチします。

+0

どのように役立ちますか? navigationStartStreamが送出された後、全体のnavigationStartStreamWithDelayストリームをキャンセルしないのですか? –

+0

@MykhailoI申し訳ありません私はあまり変わらないようにしていました。私が上記で行った編集を見て、それがもっと明確であるかどうか教えてください。 – ChrisG

+0

ありがとう、それは明らかです。 SHOW_SPINNERがディスパッチされなかった場合、HIDE_SPINNERをディスパッチしない方法があるのでしょうか? 私はロードスピナーをリファクタリングして後でそれを一般的なものにしたいので、他のネットワークリクエストにも使うことができます 店内にいくつかのカウンタを追加することを考えていて、カウンタがゼロの場合のみshowSpinnerをfalseに変更します。 そのため、以前のSHOW_SPINNERを使用しないでHIDE_SPINNERを追加すると、そのロジックが破損し、 となり、ネットワークロードスピナーとルーティングロードスピナーを区別するために店舗にいくつかのプロパティを導入する必要があります またはその他の回避策 –

関連する問題