使用 NgRx 存儲優化 Angular 內存以避免內存洩漏 (Angular memory optimization with NgRx store to avoid memory leaks)


問題描述

使用 NgRx 存儲優化 Angular 內存以避免內存洩漏 (Angular memory optimization with NgRx store to avoid memory leaks)

我們還有許多其他可觀察的訂閱來監聽 App State 的不同部分。我有幾個疑問:</p>

  • 訂閱 this.accountProgress$.subscribe(() => {...}) 仍然會導致內存洩漏嗎?如果在同一個組件中多次使用它以不同的方法獲取數據?我們是否應該在這種訂閱中也使用 takeUntil()take(1) (我們在少數地方有這個,但我不確定它是否有幫助)?或者使用 publish() + refCount()share({refCount: true})this.store.pipe(select( appState => appState.account.accountProgress))?
  • 有時我們需要dispatch 一個基於我們在訂閱中收到的值的操作,我知道這是一個 反模式,我們不應該 dispatch 訂閱中的操作,但是可以做什麼,因為很少有商店依賴於 API 響應,並且不確定何時返回將決定業務邏輯的進一步執行的數據
  • 還有其他優化方法嗎?(請注意,我們在組件中的任何地方都遵循上述 takeUntil() 語法,在處理 NgRx 存儲、效果和 Observable 時是否有任何其他方法來防止內存消耗)
反模式</strong>,我們不應該在訂閱中dispatch 一個動作,但是可以做什麼,因為很少有商店依賴於 API 響應,而且它何時返回數據非常不確定將決定業務邏輯的進一步執行</li>
  • 有沒有其他的優化方式?(請注意,我們在組件中的任何地方都遵循上述 takeUntil() 語法,在處理 NgRx 存儲、效果和 Observables 時是否有任何其他方法來防止內存消耗)
  • 反模式,我們不應該在訂閱中dispatch 一個動作,但是可以做什麼,因為很少有商店依賴於 API 響應,而且它何時返回數據非常不確定將決定業務邏輯的進一步執行
  • 有沒有其他的優化方式?(請注意,我們在組件中的任何地方都遵循上述 takeUntil() 語法,在處理 NgRx 存儲、效果和 Observable 時是否有任何其他方法來防止內存消耗)
  • 因為很少有商店依賴於 API 響應,並且不確定何時返回將決定業務邏輯的進一步執行的數據
  • 還有其他優化方法嗎?(請注意,我們在組件中的任何地方都遵循上述 takeUntil() 語法,在處理 NgRx 存儲、效果和 Observable 時是否有任何其他方法來防止內存消耗)
  • 因為很少有商店依賴於 API 響應,並且不確定何時返回將決定業務邏輯的進一步執行的數據
  • 還有其他優化方法嗎?(請注意,我們在組件中的任何地方都遵循上述 takeUntil() 語法,在處理 NgRx 存儲、效果和 Observable 時是否有任何其他方法來防止內存消耗)</li > </ul>


    參考解法

    方法 1:

    Your actual methods to handle subscriptions are great, but I think the best way to handle rxjs code in Angular is to use the async pipe and good data composition.

    You have to think in all the data needed to render your component and combine it to get just one final observable to be subscribed in HTML, in that way you can take advantage of ChangeDetectionStrategy and trackBy for *ngFor with reactive data.

    Follow these links to get a better undertanding:

    Hope I helped you a little.

    方法 2:

    Can the subscription this.accountProgress$.subscribe(() => {...}) still cause a memory leak?

    A while ago, I wrote here an answer that describes why memory leaks occur when using a Subject in RxJS. So, in this case I'd say it won't, because you're using takeUntil(this.destroyed$).

    If it is used multiple times within the same component to fetch data in different methods?

    If takeUntil is still there, there won't be any memory leaks. But, there is an important aspect that you should be aware of.
    Suppose you have a subject which has a few subscribers:

    const s = new Subject();
    
    const o1$ = s.pipe(
      a(),
      b(),
      c(),
      d(),
    );
    
    const o2$ = s.pipe(
      a(),
      b(),
    );
    

    If you subscribe to o1$ 3 times, there will be 3 distinct instances of each operator used until s.pipe, namely a, b, c, d. This might be something you'd want to avoid and you can do so by using share(), shareReplay() operators:

    const o1$ = s.pipe(
      a(),
      b(),
      c(),
      d(),
      share(),
    );
    
    // now, when `o1$` is subscribed, each of the `a‑d` operators will have exactly one instance
    o1$.subscribe()
    o1$.subscribe()
    o1$.subscribe()
    

    Should we use takeUntil() or take(1) with this kind of subscriptions as well

    It depends, take(n) will complete after the n‑th values has been emitted and takeUntil(notifier$) will complete when notifier$ emits.

    Sometimes we need to dispatch an action based on the value we receive within the subscription ...

    Maybe instead of doing this in the subscription, you can use the tap operator, which is well‑known for side effects.

    data$ = this.store.select(yourSelector).pipe(
      /* ... */
      tap(result => this.store.dispatch(anAction))
      /* ... */
    )
    

    Also, the data$ observable from above can be used in conjunction with the async pipe, so you don't have to deal with manual subscription/unsubscription.

    (by patrick.1729Gustavo AlarcónAndrei Gătej)

    參考文件

    1. Angular memory optimization with NgRx store to avoid memory leaks (CC BY‑SA 2.5/3.0/4.0)

  • #ngrx-effects #Angular #ngrx-store #rxjs #memory-leaks






    相關問題

    rxjs減少不繼續 (rxjs reduce does not continue)

    從 reducer/action 觸發 API 重新加載的正確方法是什麼? (What's the proper way to trigger the API reload from reducer/action?)

    Angular NgRx 效果,如何傳遞參數? (Angular NgRx effects, how to pass a parameter?)

    NgRx 效果無限循環 (NgRx Effects infinite loop)

    發送 forkjoin api,每個 api 之間有延遲 (Send forkjoin api with a delay in between each api)

    如何從所有待處理的請求中取消特定請求 (How to cancel specific request from all pending request)

    使用 NgRx 存儲優化 Angular 內存以避免內存洩漏 (Angular memory optimization with NgRx store to avoid memory leaks)

    NgRx EffectsModule 導入組 (NgRx EffectsModule imports group)

    切換地圖後在NGRX特效點擊功能中獲取動作道具 (Get action props in the NGRX effects tap function after switch Map)

    如何防止在 NgRx 中第二次加載數據? (How prevent loading data second time in NgRx?)

    需要幫助了解這種 Ngrx 效果 (Need help understanding this Ngrx effect)

    測試效果 NgRx Angular 11 (Testing effects NgRx Angular 11)







    留言討論