如何在angular2应用程序中使用ngrx-effects从商店返回分页数据或从api服务返回新数据?

tre*_*orc 2 javascript redux ngrx ngrx-effects angular

我的问题是关于redux商店中分页数据形状的这个优秀问题和答案的延续.我在角度2应用程序中使用ngrx/store.

{
  entities: {
    users: {
      1: { id: 1, name: 'Dan' },
      42: { id: 42, name: 'Mary' }
    }
  },
  visibleUsers: {
    ids: [1, 42],
    isFetching: false,
    offset: 0
  }
}
Run Code Online (Sandbox Code Playgroud)

基于上述形状,我相信如果来自传入请求有效负载的偏移(或页面,排序等)发生变化,则可见用户将通过调用DB来改变用户实体.我有一些动作和reducer函数来处理它,它按预期工作.如果偏移量保持不变并且用户以他们离开的方式返回页面,则应该由商店而不是DB返回用户实体.

我奋力就是把那个逻辑和rxjs运营商使用(仍然在学习这一点).

认为正确的地方是一种效果.以下是我现在在angular2应用程序(我正在注入Actions,Store和我的UserService)中的内容,每次加载页面时都会提取新数据.

@Effect loadUsers$ = this.actions$
     .ofType('LOAD_USERS')
     .switchMap(() => this.userService.query()
         .map((results) => {
             return new LoadUsersSuccessAction(results);
         }))
     .catch(() => Observable.of(new LoadUsersFailureAction()));
Run Code Online (Sandbox Code Playgroud)

我最好的想法是这样的:

@Effect loadUsers$ = this.actions$
     .ofType('LOAD_USERS')
     .withLatestFrom(this.store.select(state => state.visibleUsers.offset))
     .switchMap(([action, state]) => {
         //something that looks like this??
         //this syntax is wrong and I can't figure out how to access the action payload
         state.offset === payload.offset 
            ? this.store.select(state => state.entities.users) 
            : this.userService.query()
         }
         .map((results) => {
             return new LoadUsersSuccessAction(results);
         }))
     .catch(() => Observable.of(new LoadUsersFailureAction()));
Run Code Online (Sandbox Code Playgroud)

不知道如何使这项工作.谢谢你.

tre*_*orc 5

我不喜欢回答我自己的问题,但我花了很长时间才找到答案.我不接受这个答案,因为我不确定这是解决问题的最佳方法(仍在学习输入/输出).然而,它确实完美.

我在github gist中找到了正确的语法.此代码与我的示例不匹配,但它通过使用某种条件返回存储或api observable清楚地演示了"条件ngrx效果的2个选项".

希望这有助于某人.

这里是:

  @Effect()
  selectAndLoadStore$: Observable<Action> = this.actions$
    .ofType(storeActions.SELECT_AND_LOAD_STORE)
    .withLatestFrom(this.store.select(ngrx.storeState))
    .map(([action, storeState]) => [action.payload, storeState])
    .switchMap(([storeName, storeState]) => {
      const existsInStore = Boolean(storeState.urlNameMap[storeName]);
      return Observable.if(
        () => existsInStore,
        Observable.of(new storeActions.SetSelectedStore(storeName)),
        this.storeService.getByUrlName(storeName)
          .map(store => new storeActions.LoadSelectedStoreSuccess(store))
      );
    });

  @Effect()
  selectAndLoadStore$: Observable<Action> = this.actions$
    .ofType(storeActions.SELECT_AND_LOAD_STORE)
    .withLatestFrom(this.store.select(ngrx.storeState))
    .map(([action, storeState]) => [action.payload, storeState])
    .switchMap(([storeName, storeState]) => {
      const existsInStore = Boolean(storeState.urlNameMap[storeName]);
      let obs;
      if (existsInStore) {
        obs = Observable.of(new storeActions.SetSelectedStore(storeName));
      } else {
        obs = this.storeService.getByUrlName(storeName)
          .map(store => new storeActions.LoadSelectedStoreSuccess(store));
      }
      return obs;
    });
Run Code Online (Sandbox Code Playgroud)