发起效果和行动的最佳实践
Best Practice to initiate Effect and action
所以我花了很多时间让这两种方法起作用,特别是所有 ngrx 操作员。然而,我无法决定哪种方法最适合我正在处理的用例。
所以我有以下情况:
- 在页面加载时,我确保用户已登录,并在
auth
功能状态下加载所有用户数据。
- 我还想在
settings
功能状态下加载页面加载时的所有设置,但是从 api 加载设置需要具有当前用户 ID,我从上一个步骤。
我的店铺模型如下:
所以我为完成这项工作而实施的两种方法是:
第一种方法
- 我在这里加载用户数据,
- 每当我收到它的效果时,
- 我调度加载设置的
AllSettingsRequested
操作。
@Effect({dispatch: false})
loadUser$ = this.actions$
.pipe(
ofType<UserRequested>(AuthActionTypes.UserRequested),
withLatestFrom(this.store.pipe(select(isUserLoaded))),
filter(([action, _isUserLoaded]) => !_isUserLoaded),
mergeMap(([action, _isUserLoaded]) => this.auth.getUserByToken()),
tap(_user => {
if (_user) {
this.store.dispatch(new UserLoaded({ user: _user }));
this.store.dispatch(new AllSettingsRequested()); /* Dispatch the Load Settings Action */
} else {
this.store.dispatch(new Logout());
}
}),
catchError(err => {
console.log(err);
return of([]);
})
);
然后在设置效果中我可以简单地添加以下内容:
@Injectable()
export class SettingsEffects {
loadSettings = createEffect(() => this.actions$.pipe(
ofType(SettingsActionTypes.AllSettingsRequested),
withLatestFrom(this.store.pipe(select(currentUser))),
mergeMap( ([action, user]) =>
this.settingsService.getSettings( user.id )
),
map(s => {
return new AllSettingsLoaded({settings: s.model});
})
))
}
方法工作正常,但是从 UserLoaded 效果调度 SettingsRequest 操作感觉不对。
第二种方法
第二种方法是在页面加载时启动 SettingsRequested 操作,让效果等到用户数据加载完毕,然后调用设置 api 并加载设置。
@Injectable()
export class SettingsEffects implements OnInitEffects {
loadSettings = createEffect(() => this.actions$.pipe(
ofType(SettingsActionTypes.AllSettingsRequested),
mergeMap(action => {
console.log("im here");
return combineLatest(
of(action),
this.store.pipe(select(currentUser))
)
}
),
skipWhile(([action, currentUser]) => {
console.log('Checking Current User.. ' + currentUser);
return (!currentUser);
}),
mergeMap( ([action, user]) =>
this.settingsService.getSettings( user.id )
),
map( (s) => {
return new AllSettingsLoaded({settings: s.model});
})
));
/* Dispatch the action on page load */
ngrxOnInitEffects(): Action {
return { type: SettingsActionTypes.AllSettingsRequested };
}
如您所见,这里的效果变得更加复杂,但是,我不需要像第一种方法那样从用户加载效果中分派 SettingsRequest 操作。
我希望我能够阐明问题和两种方法。我的问题是,就 ngrx 最佳实践而言,哪种方法更有意义?
我会选择第三种方法。
我不会从方法一中调度 UserLoaded
和 AllSettingsRequested
,而是直接调度 UserLoaded
。设置效果可以监听这个动作并获取设置。通过这样做,您也不必从商店中读取用户 ID,因为它存在于 UserLoaded
操作中。
所以我花了很多时间让这两种方法起作用,特别是所有 ngrx 操作员。然而,我无法决定哪种方法最适合我正在处理的用例。
所以我有以下情况:
- 在页面加载时,我确保用户已登录,并在
auth
功能状态下加载所有用户数据。 - 我还想在
settings
功能状态下加载页面加载时的所有设置,但是从 api 加载设置需要具有当前用户 ID,我从上一个步骤。
我的店铺模型如下:
所以我为完成这项工作而实施的两种方法是:
第一种方法
- 我在这里加载用户数据,
- 每当我收到它的效果时,
- 我调度加载设置的
AllSettingsRequested
操作。
- 我调度加载设置的
@Effect({dispatch: false})
loadUser$ = this.actions$
.pipe(
ofType<UserRequested>(AuthActionTypes.UserRequested),
withLatestFrom(this.store.pipe(select(isUserLoaded))),
filter(([action, _isUserLoaded]) => !_isUserLoaded),
mergeMap(([action, _isUserLoaded]) => this.auth.getUserByToken()),
tap(_user => {
if (_user) {
this.store.dispatch(new UserLoaded({ user: _user }));
this.store.dispatch(new AllSettingsRequested()); /* Dispatch the Load Settings Action */
} else {
this.store.dispatch(new Logout());
}
}),
catchError(err => {
console.log(err);
return of([]);
})
);
然后在设置效果中我可以简单地添加以下内容:
@Injectable()
export class SettingsEffects {
loadSettings = createEffect(() => this.actions$.pipe(
ofType(SettingsActionTypes.AllSettingsRequested),
withLatestFrom(this.store.pipe(select(currentUser))),
mergeMap( ([action, user]) =>
this.settingsService.getSettings( user.id )
),
map(s => {
return new AllSettingsLoaded({settings: s.model});
})
))
}
方法工作正常,但是从 UserLoaded 效果调度 SettingsRequest 操作感觉不对。
第二种方法
第二种方法是在页面加载时启动 SettingsRequested 操作,让效果等到用户数据加载完毕,然后调用设置 api 并加载设置。
@Injectable()
export class SettingsEffects implements OnInitEffects {
loadSettings = createEffect(() => this.actions$.pipe(
ofType(SettingsActionTypes.AllSettingsRequested),
mergeMap(action => {
console.log("im here");
return combineLatest(
of(action),
this.store.pipe(select(currentUser))
)
}
),
skipWhile(([action, currentUser]) => {
console.log('Checking Current User.. ' + currentUser);
return (!currentUser);
}),
mergeMap( ([action, user]) =>
this.settingsService.getSettings( user.id )
),
map( (s) => {
return new AllSettingsLoaded({settings: s.model});
})
));
/* Dispatch the action on page load */
ngrxOnInitEffects(): Action {
return { type: SettingsActionTypes.AllSettingsRequested };
}
如您所见,这里的效果变得更加复杂,但是,我不需要像第一种方法那样从用户加载效果中分派 SettingsRequest 操作。
我希望我能够阐明问题和两种方法。我的问题是,就 ngrx 最佳实践而言,哪种方法更有意义?
我会选择第三种方法。
我不会从方法一中调度 UserLoaded
和 AllSettingsRequested
,而是直接调度 UserLoaded
。设置效果可以监听这个动作并获取设置。通过这样做,您也不必从商店中读取用户 ID,因为它存在于 UserLoaded
操作中。