博客地址:https://indepth.dev/posts/120…
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.
Spartacus 里的例子, 并没有应用 forRoot 办法。
effects 输出参数是一个数组:
这些都是具体的 effect 实现 class:
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:
effect ---->actions
|- 被 store intercept
actions$
AC 的含意是一个类型:extends ActionCreator<string, Creator>
V = Action,V 如果不指定,默认类型为 Action:
- 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:
看看 Observable.pipe 的实现:
export class Observable<T> implements Subscribable<T> {
/* ... */
pipe<A, B>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>): Observable<B>;
/* ... */
}
where OperatorFunction<T,A> specifies the type of a function that receives an observable as a parameter and returns another observable:
OperatorFunction: 接管两个类型参数,T 代表原始 Observable 包裹的类型,A 示意返回的新的 Observable 蕴含的类型。
最终返回一个新的 Observable,类型为 B.
Store.dispatch(event)
It signals that an event that requires state changes is sent from the UI(e.g a smart component).
Store.dispatch() will push the action(event) into an actions stream(which is different from the one that belongs to the effects):
Action
能够了解成指令,通过 UI / Service / Effects 来 dispatch.
Creator<P, R> is simply a function takes up a parameter of type P and returns an object of type R.
reducer
Reducers are pure functions that are responsible for state changes.
reducer 的 interface 定义:
export interface ActionReducer<T, V extends Action = Action> {(state: T | undefined, action: V): T;
}
上述语法定义了一个 interface,该 interface 形容了一个函数类型,大括号内是函数类型的具体定义,小括号为这个函数的输出接口定义,该函数接管两个输出参数,形参为 state 和 action,类型别离为 T(也能够承受 undefined) 和 V, 小括号前面的冒号,定义了返回参数类型也应该为 T.
很显著,这个函数就是一个状态机,基于以后状态和输出的 action(能够了解成指令,触发状态迁徙的指令),返回新的状态。
TypeScript 里通过定义接口来形容函数 signature 的这种形式,曾经和 ABAP 里的 interface 很不一样了。
以 address-verification.reducer.ts 里的 reducer 为例:该 reducer 如何被 setup?
在 index.ts 里,通过 import * as 来辨别这些同名的 reducer:
通过 getReducers 对立返回:
通过 reducerToken 和 getReducers 提供 provider 信息:
Provider 在 @NgModule 提供的元数据里应用:
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
| |
-------------
更多 Jerry 的原创文章,尽在:” 汪子熙 ”: