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



我的问题延续了这个关于 redux 存储中分页数据形状的优秀问题和答案。 我正在一个角度 2 应用程序中使用 ngrx/store。

{
entities: {
users: {
1: { id: 1, name: 'Dan' },
42: { id: 42, name: 'Mary' }
}
},
visibleUsers: {
ids: [1, 42],
isFetching: false,
offset: 0
}
}

基于上述形状,我相信如果来自传入请求有效负载的偏移量(或页面、排序等)发生变化,那么可见用户以及用户实体将通过调用数据库而改变。 我有一些操作和化简器函数来处理这个问题,它按预期工作。 如果偏移量保持不变,并且用户以他们离开页面的方式返回到页面,则用户实体应由存储而不是数据库返回。

我苦苦挣扎的地方是在哪里放置该逻辑以及使用哪些 rxjs 运算符(仍在学习这个)。

我认为正确的地方是一种效果。 这是我现在在我的 angular2 应用程序(我正在注入操作、商店和我的用户服务)中拥有的内容,每次加载页面时都会提取新数据。

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

我最好的主意是这样的:

@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()));

不知道如何使这项工作。 谢谢。

我不喜欢回答自己的问题,但我花了很长时间才找到答案。 我不会接受这个答案,因为我不确定这是最好的方法(仍在学习来龙去脉)。 但是,它确实可以完美地工作。

我在 github gist 中找到了正确的语法。 这段代码与我的示例不匹配,但它清楚地展示了"条件 ngrx 效果的 2 个选项",方法是使用某种条件返回可观察的存储或 api。

希望这对某人有所帮助。

在这里:

@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;
});

最新更新