我有一个场景,我需要在我的Angular应用程序中对两个@Ngrx动作进行排序。
第一个操作使用某些数据更新状态,第二个操作使用该数据触发服务器调用。我正在使用效果对两个动作进行排序,并且仅在第一个动作完成后触发第二个动作。
为了确保第二个操作包括来自状态的最近更新的数据,我将存储注入我的效果并使用选择器函数来检索数据并将其作为第二个操作的有效负载包含在内。
这有效。
我的问题
但是,我相信由于this.actions$
已经是一个可观察的流,我应该能够简单地转换该流上的每个事件并将其转换为不同的动作。
我想到的粗略的大理石图:
我正在使用withLatestFrom
运算符将动作流与来自状态的数据相结合。
@Effect()
lazyEffect1$ = this.actions$.ofType(LazyActions.TEST_ACTION_SEQUENCE)
.withLatestFrom(this.filterId$, (x, y) => {
return new LazyActionDone(y.number);
});
但是这段代码给了我一个错误:
TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
我已经能够使用稍微不同的构造来实现这一点,这也包含在下面的代码中。
但我想了解为什么lazyEffect1
无效。我的理解在哪里失败了?
代码
NgRx减速机:
// reducers.ts
export function lazyReducer(
state: any = {},
action: LazyAction | LazyActionDone
) {
switch (action.type) {
case LazyActions.TEST_ACTION_SEQUENCE: {
console.info('Action Received in Reducer: ', action.type);
return {
...state,
number: action.payload
};
}
case LazyActions.TEST_ACTION_SEQUENCE_DONE: {
console.info('Done Received in Reducer: ', action.type);
return {
...state,
retrieved: action.payload,
done: true
};
}
default: {
return state;
}
}
}
NgRx效果:
// effects.ts
@Injectable()
export class LazyEffects {
private filterId$: Observable<any>;
constructor(
private actions$: Actions,
private store: Store<any>
) {
this.filterId$ = this.store.select(getLazyState);
}
// THIS DOES NOT WORK
@Effect()
lazyEffect1$ = this.actions$.ofType(LazyActions.TEST_ACTION_SEQUENCE)
.withLatestFrom(this.filterId$, (x, y) => {
// console.info(x, y);
return new LazyActionDone(y.number);
});
// THIS WORKS
@Effect()
lazyEffect2$ = this.actions$.ofType(LazyActions.TEST_ACTION_SEQUENCE)
.switchMap((action) => {
console.info('Action Received in Effects: ', action.type);
return of(action).withLatestFrom(this.filterId$, (x, y) => new LazyActionDone(y.number));
});
}
只是拼出解决方案@cartant provided ..我相信解决方案是替换这个属性:
// THIS DOES NOT WORK
@Effect()
lazyEffect1$ = this.actions$.ofType(LazyActions.TEST_ACTION_SEQUENCE)
.withLatestFrom(this.filterId$, (x, y) => {
// console.info(x, y);
return new LazyActionDone(y.number);
});
有了这个功能:
@Effect()
lazyEffect1$() {
return this.actions$.ofType(LazyActions.TEST_ACTION_SEQUENCE)
.withLatestFrom(this.filterId$, (x, y) => {
// console.info(x, y);
return new LazyActionDone(y.number);
});
}
@cartant在评论中应该得到他的回答,但是我想为遇到这个问题的其他人提供答案/示例,并且没有注意到答案在评论中。