启动效果和行动的最佳实践

时间:2019-11-16 16:02:35

标签: angular rxjs ngrx ngrx-store ngrx-effects

因此,我花了很多时间使这两种方法都起作用,特别是与所有ngrx运算符一起使用。但是,我无法确定哪种方法是我正在使用的用例的最佳方法。

所以我有以下情况:

  1. 在页面加载时,我确保用户已登录,并以auth功能状态加载所有用户数据。
  2. 我还希望以settings功能状态加载页面加载时的所有设置,但是从api加载设置需要具有我从上一步获得的当前用户ID。

我的商店的建模如下:

enter image description here

因此我实现该工作的两种方法是:

第一种方法

  1. 我在此处加载用户数据,并且
  2. 只要我收到效果,
    1. 我调度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操作感觉不正确。

第二种方法

第二种方法是在页面加载时启动SettingsRequestedAction,并使其效果等到加载用户数据后再调用设置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 };
    }

您可以看到这里的效果变得更加复杂,但是,我不需要像第一种方法一样从userload效果中调度SettingsRequest操作。

我希望我能够阐明问题和两种方法。我的问题是,就ngrx最佳做法而言,哪种方法更有意义?

1 个答案:

答案 0 :(得分:0)

我会选择第三种方法。

我不会从方法一中调度UserLoadedAllSettingsRequested,而是调度UserLoaded。设置效果可以收听此操作并获取设置。通过这样做,您也不必从商店中读取用户ID,因为它存在于UserLoaded操作中。