天天看點

深入了解 ngrx effect 背後的工作機制Store

部落格位址: https://indepth.dev/posts/1206/understanding-the-magic-behind-ngrx-effects

an action is a constituent of a reducer, as well as of an effect. NgRx ensures that actions are first handled by the reducers, after which they will eventually be intercepted by the effects.

actions 是 reducer 的組成部分,也是 effect 的組成部分。 NgRx 確定操作首先由 reducer 處理,之後它們最終會被 effect 攔截。

Reducer 處理 action,然後被 effect 解析。

Providing the effects

forRoot 和 forFeature 接收的輸入參數是其他 .ts 檔案 export 的 class, 而不是具體的 class 執行個體。根據 class 獲得 metadata.

EffectsModule.forRoot 隻能被調用一次,因為這個方法還會執行個體化其他 Ngrx 重要的服務,比如 EffectsRunner 和 EffectSources.

深入了解 ngrx effect 背後的工作機制Store
Spartacus 裡的例子, 并沒有使用 forRoot 方法。
深入了解 ngrx effect 背後的工作機制Store
深入了解 ngrx effect 背後的工作機制Store

Once the effects (classes) are registered, in order to set them up, an observable will be created (with the help of EffectSources) and subscribed to (thanks to EffectRunner);

reducer: the shape of application

state entity: where the app information is kept, also where the place actions meet reducers, meaning it’s where reducers being invoked, which may cause state changes

State 相當于模型層,而 Store 隻是消費者和 State 之間的中間件。

state 是應用程式存儲資料的地方。

the Store entity - the middleman between the data consumer(e.g: a smart component) and the model(the State entity)

Store 是資料消費者,比如 Angular Component 和 model(就是 state entity) 之間的中間層。

effects 會被 merge.

all the effects(e.g: those created by createEffect for example) will be merged into one single observable whose emitted values will be actions.

Effects 會被 merge 成一個 Observable,後者 emit 的value 就是 actions.

Store 也是 stream 的 Observer:

深入了解 ngrx effect 背後的工作機制Store

effect ---->actions
                |- 被 store intercept
      
深入了解 ngrx effect 背後的工作機制Store

ScannedActionsSubject: comes from @ngrx/store and it is a Subject(thus, an Observable) that emits whenever actions are dispatched, but only after the state changes have been handled.

So, when an action is dispatched(Store.dispatch()), the State entity will first update the application state depending on that action and the current state with the help of the reducers, then it will push that action into an actions stream, created by ScannedActionsSubject.

Store dispatch 之後,首先狀态機遷移,應用程式 state 發生變化,這一系列通過 reducer 驅動。然後把 action push 到 action stream 去。

By setting the Actions’ source to ScannedActionsSubject, every time we have something like this.actions$.pipe().subscribe(observer) the observer will be part of ScannedActionsSubject’s observers list, meaning that when the subject emits an action(e.g: subject.next(action)), all the registered observers will receive it. This should explain why all the effects will receive the same actions, but, with ofType’s help, these can be filtered out - OfType 的過濾效果。

OfType

In order to determine which actions should trigger which effects, the OfType custom operator is used.

維護 action 和 effect 的映射關系。

OfType 内部也是用的 RxJS 的 filter Operator:

export class Observable<T> implements Subscribable<T> {
  /* ... */
  
  pipe<A, B>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>): Observable<B>;
  
  /* ... */
}
      
深入了解 ngrx effect 背後的工作機制Store
深入了解 ngrx effect 背後的工作機制Store
深入了解 ngrx effect 背後的工作機制Store

Store

并不存儲資料,隻是一個中間件。

源代碼:

export class Store<T> extends Observable<T> implements Observer<Action> {
  constructor(
    state$: StateObservable,
    private actionsObserver: ActionsSubject,
    private reducerManager: ReducerManager
  ) {
    super();

    this.source = state$;
  }
  
  /* ... */
}
      

Store 從外界接受資料,即 state$.

Every time the source (state$) emits, the Store class will send the value to its subscribers.
allows consumer ↔️ state communication
        ⬆️
        |
        |
-----------      newState          -----------                         
|         | <-------------------   |         |                         
|         |  Store.source=$state   |         |
|         |                        |         | <---- storing data 
|  Store  |      Action            |  State  |                         
|         | -------------------->  |         |
|         |   Store.dispatch()     |         |          
-----------                        ----------- 
                                   |        ⬆️
                          Action   |        | newState
                                   |        |
                                   ⬇️        |
                                  ------------- 
                                  |           | 
                                  |  Reducer  | <---- state changes
                                  |           | 
                                  -------------
      
深入了解 ngrx effect 背後的工作機制Store