咱们能够应用 Meta Reducer 即高阶 Reducer 的概念。
上面是一个典型的例子:Logger Meta Reducer.
该高阶 Reducer 在实在的归约器执行之前增加一些日志音讯:
export function logger(reducer:
ActionReducer<AppState>): ActionReducer<AppState> {return (state: AppState, action: any): AppState => {console.log('state', state);
console.log('action', action);
return reducer(state, action);
};
}
logger 的输出是一个 reducer,返回一个新的与输出的 reducer 具备完全相同的签名的新 reducer,且在这个新的 reducer 里,会首先执行日志记录操作。这有点像 Java 里的面向切片编程技术 (AOP).
所示的 logger() 元归约器函数承受 ActionReducer 类型的输出参数(即纯函数或归约器),并且还返回 ActionReducer 类型的函数。返回的函数在返回包装的减速器之前将状态和操作变量记录到控制台。
回到 App Module 代码,定义一组 ModuleWithProviders 类来包装 StoreDevtoolsModule.instrument() 办法,以便稍后在 App Module 上导入它。
export const storeDevTools:
ModuleWithProviders[] =
!environment.production ? [StoreDevtoolsModule.instrument()] : [];
最初,将上述的 ModuleWithProviders 导入 App Module:
StoreModule.forRoot((reducers) as any,
{metaReducers}),
EffectsModule.forRoot(effects),
storeDevTools,
实际上,StoreModule.forRoot() 办法还能够接管第二个参数,类型为 StoreConfig interface:
export declare type StoreConfig<T,
V extends Action = Action> = {
initialState?: InitialState<T>;
reducerFactory?: ActionReducerFactory<T, V>;
metaReducers?: MetaReducer<T, V>[];
Store Side-Effect
将 Action 分派到 Store 的代码有时会导致一些副作用 (Side Effect)。例如,调度一个动作来将所有 Hero 数据加载到应用程序中。这样的操作会导致必须通过 Angular 服务与托管在服务器端(或云)上的 Web API 进行通信以返回英雄数据的 Side-Effect。将操作分派到 Store 的代码的这种 Side-Effect,会导致与内部服务的通信。
Ngrx/effects 模块将副作用与容器组件隔离开来,并提供了一个简洁的解决方案来在反对 NgRX Store 的 Angular 应用程序中解决它们。Ngrx/store 模块向 Store 发送一个操作,以传递从服务器检索到的任何后果或数据。
上图的交互场景概述如下:
- ngrx/effects 模块监听散发到 Store 的动作。
- 如果有一个 Effect 被钩住来监听一个分派的动作,这个 Effect 就会运行并执行。
- 一旦 Effect 从服务器端接管到数据,它就会向 Store 发送一个新的 action,以便 reducer 启动并解决从 Effect 接管到的数据并相应地更新状态。