如何在NgRx Effects中替换Facade代码?寻求最佳实践方案
解决NgRx Effects中调用Facade的最佳实践问题
问题根源
在NgRx架构里,Facade的核心职责是为组件层封装Store的操作(分发Action + 选择数据),而Effects的作用是监听Action流、处理副作用并触发新的Action。在Effects里调用Facade会打破职责边界,增加模块耦合,还会让Effects的逻辑变得不透明——得深入Facade内部才能知道实际触发了哪些Action。
优化方案:直接在Effects中分发Action
你的Facade方法本质都是调用store$.dispatch()触发对应Action,所以在Effects里可以跳过Facade,直接导入并触发这些Action,既符合NgRx单向数据流设计,又能让逻辑更清晰。
重构后的Effects代码
import * as countListActions from '../../count-list/store/count-list.actions'; import * as countDetailsActions from '../../count-details/store/count-details.actions'; // 其他必要导入... closeCountSuccess$ = createEffect(() => this.actions$.pipe( ofType(CountActions.CountActionTypes.CLOSE_COUNT_SUCCESS), switchMap((action: fromActions.CountSuccess) => { // 直接分发对应Action,替代Facade调用 this.store$.dispatch(new countListActions.Reset()); this.store$.dispatch(new countListActions.SetPageNumber({ pageNumber: 0 })); this.store$.dispatch(new countListActions.GetCountListRequest({ page: 0, size: 20 })); this.store$.dispatch(new countDetailsActions.SetCurrentCountRequest()); this.openSimpleSnackbar( this.translateService.instant('content.count-is-successfully-closed'), 5000, G3SnackType.Success ); return of(new fromActions.WizardCloseDialog()); }) ) );
保留Facade的原有职责
CountFacade依然保留给组件使用,组件通过Facade封装的方法操作Store,确保组件层代码简洁,同时Effects层直接和Store交互,职责更单一:
// Facade代码保持不变,供组件调用 @Injectable({ providedIn: 'root' }) export class CountFacade { constructor(private store$: Store<CountState>) {} // ...原有方法不变,组件调用这些方法触发Action fetchCountList({ page, size }) { this.store$.dispatch(new countListActions.GetCountListRequest({ page: page, size: size })); } resetCountList() { this.store$.dispatch(new countListActions.Reset()); } // ...其他方法 }
额外优化建议(可选)
如果想让显示Snackbar这类副作用也遵循Action驱动模式,可以抽成单独的Effect:
- 定义
ShowSuccessSnackbarAction - 创建监听该Action的Effect,在里面调用
openSimpleSnackbar - 在
closeCountSuccess$Effect中分发这个Action,替代直接调用方法
这样所有副作用都通过Action触发,更符合NgRx纯函数、可追踪的设计理念。
内容的提问来源于stack exchange,提问作者robi
相关产品推荐
相关产品推荐

