如何同时分派多个ngrx操作

时间:2019-09-25 02:26:34

标签: angular typescript redux rxjs ngrx

我正在使用ngrx,并且有一个Scenerio,需要同时分派2个动作。我的州有待更新和更新的属性,如下所示。

//from reducer
const defaultCardState: CardState = {
    ids: [],
    entities: {},
    loaded: false,
    loading: false,
    adding: false,
    added: false,
    updating: false,
    updated: false,
    deleting: false,
    deleted: false
};

这些是我从组件中分派的操作

this.store.dispatch(fromCard.updateCard({id: id1, changes: {name: name1}}))
this.store.dispatch(fromCard.updateCard({id: id2, changes: {name: name2}}))

下面是我的动作,减速器和效果

//Update Card Actions
export const updateCard = createAction('[Cards] Update Card', props<{id: string, changes: any}>())
export const updateCardSuccess = createAction('[Cards] Update Card Success', props<{changes: any}>());
export const updateCardFail = createAction('[Cards] Update Card Fail')

//Reducer
on(fromCards.updateCard, (state) => ({...state, updating: true, updated: false})),
    on(fromCards.updateCardSuccess, (state, action: any) => ({...cardAdapter.updateOne(action.changes, state), updated: true, updating: false})),
    on(fromCards.updateCardFail, (state, action: any) => fromCards.updateCardFail),

//Update Card Effect
updateCard$: Observable<Action> = createEffect(() => this.actions$.pipe(
    ofType(fromCardActions.updateCard),
    map((action: any) => { return {id: action.id, changes: action.changes}}),
    switchMap((action: any) => this.cardService.updateCard(action).pipe(
        map((res) => (fromCardActions.updateCardSuccess({changes: action }))),
        catchError(() => of(fromCardActions.updateCardFail))
    ))
))

什么是最好的方法来一次又一次地分派这些操作,以使更新字段和更新字段不会冲突?如果仅运行其中之一,则可以运行,但是如果如上所述将它们一起分发,则只有一个完成。我看到这两个动作都被调度了,但是只有一个成功动作被调度了。

5 个答案:

答案 0 :(得分:2)

类似于Tony的答案,但使用正确的运算符:

\n

答案 1 :(得分:1)

您没有,您对有效载荷采取了不同的操作,该有效载荷需要一张纸牌而不是一张纸牌,然后减速器返回用多张纸牌更新的新状态。您的api还应该能够接受数组,以便您的效果可以将多个发送到服务器。

答案 2 :(得分:0)

您可以在效果中调度多个动作,我建议您仅在效果中执行该动作

请考虑以下示例

@Effect()
dispatchMultiAction$: Observable<Action> = this.actions$.pipe(
    ofType<SomeAction.Dispatch>(someActions.Dispatch),
    switchMap(_ =>
        of(
            new someActions.InitData(),
            new someActions.GetData(),
            new someActions.LoadData()
        )
    )
);

答案 3 :(得分:0)

从技术上讲,使用动作来分派另一个多个动作确实是很糟糕的做法。它增加了应用程序的复杂性。一段时间后,您将无法调试并了解为什么和将要分派操作。这段视频Mike Ryan用NgRx描述了良好的行动卫生: https://youtu.be/JmnsEvoy-gY?t=285

答案 4 :(得分:0)

类似于 xandermonkey 的答案,但使用正确的运算符:

@Effect()
dispatchMultiAction$: Observable<Action> = this.actions$.pipe(
    ofType<SomeAction.Dispatch>(someActions.Dispatch),
    concatMap(_ => [
            new someActions.InitData(),
            new someActions.GetData(),
            new someActions.LoadData()
        ])
    )
);

注意 concatMap 和 mergeMap 的区别。因为 concatMap 在前一个完成之前不会订阅下一个 observable,所以将首先发出延迟 2000 毫秒的来自源的值。将此与立即订阅内部 observable 的 mergeMap 进行对比,具有较小延迟(1000 毫秒)的 observable 将发出,然后是需要 2000 毫秒才能完成的 observable。