这是我的应用程序模块:
@NgModule({
declarations: [
SampleA
],
imports: [
BrowserModule,
EffectsModule.forRoot([APIEffects]),
HttpClientModule,
StoreModule.forRoot(reducers),
StoreDevtoolsModule.instrument({
maxAge: 25, // Retains last 25 states
logOnly: environment.production, // Restrict extension to log-only mode
}),
KeyboardShortcutsModule.forRoot()
],
providers: [
APIService,
{
provide: HTTP_INTERCEPTORS,
useClass: HttpMockRequestInterceptor,
multi: true
}
],
bootstrap: [],
entryComponents: [
SampleComponent
]
})
export class AppModule{...}
这里是APIEffect
:
@Injectable()
export class APIEffects {
fetchData$ = createEffect(() => this.actions$.pipe(
ofType(Actions.apiFetchData),
mergeMap((action) => this.apiService.fetchData(...action)
.pipe(
map(data => Actions.apiSuccess({ data })),
catchError(() => of(Actions.apiCallFailed()))
)
)
));
}
现在,如果我在apiFetchData
构造函数中分配SampleComponent
操作,则不会调用该效果:
export class SampleComponent {
constructor(private store: Store<{ state: State }>) {
store.dispatch(Actions.apiFetchData(...))
}
}
如果我稍后在组件的生命周期中调度相同的操作,则一切正常,并且效果发生了。
在Redux DevTools
中,我可以看到在effects init
之前发生了动作分配。这是顺序:
@ngrx/store/init
[API] fetch data // this is the fetch data action
@ngrx/effects/init
所以我的问题是如何在构造组件之前强制效果初始化。
为了实现,您可能希望查看NGRX生命周期事件,例如ROOT_EFFECTS_INIT
,如下所述:https://ngrx.io/guide/effects/lifecycle
使用APP_INITIALIZER
注入令牌(很好的教程here)加上必要的语法糖,您可以构造一个应用程序初始化程序服务,该服务将延迟应用程序自举,直到注册了NGRX根效果为止(在这种情况下,不会初始化任何组件,并且您上面的逻辑在构造函数中应该起作用)。在最近的项目中,我走了一条类似的路:
export class AppInitializer {
constructor(private readonly actions$: Actions) {}
initialize() {
return this.actions$.pipe(ofType(ROOT_EFFECTS_INIT));
}
}
return (): Promise<any> => {
return appInitializer.initialize().toPromise();
};
}
...最后将提供程序添加到您的模块中:
import { appInitializerFactory } from './app-initializer.factory';
export const APP_INITIALIZER_PROVIDER: Provider = {
provide: APP_INITIALIZER,
useFactory: appInitializerFactory,
deps: [AppInitializer],
multi: true,
};
// your module...
{
...
providers: [APP_INITIALIZER_PROVIDER]
...
}