redux 如何同时分派多个ngrx操作

k4ymrczo  于 2023-02-08  发布在  其他
关注(0)|答案(5)|浏览(128)

我正在使用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))
    ))
))

什么是一个接一个地分派这些操作的最佳方法,这样更新和更新的字段就不会冲突?如果我只运行其中一个,它就可以工作,但是如果我像上面所示的那样一起分派它们,只有一个完成。我看到两个操作都被分派了,但是只有一个成功的操作被分派了。

pbossiut

pbossiut1#

与Tony的答案相似,但使用了正确的运算符:

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

bkhjykvo2#

你可以在你的效果中分派多个动作,我建议你只在效果中这样做
考虑以下示例

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

o2gm4chl3#

你不需要,你有一个不同的动作,它的有效载荷是一个卡片数组而不是一张卡片,然后reducer返回用多张卡片更新的新状态。你的API也应该能够接受一个数组,这样你的效果就可以发送多张卡片到服务器。

vhipe2zx

vhipe2zx4#

使用一个操作来调度多个其他操作是不好的做法,因为这会增加应用的复杂性。随着应用的增长,调试操作并推断其来源会变得越来越困难。Mike Ryan的演讲介绍了NgRx的良好操作卫生:https://youtu.be/JmnsEvoy-gY?t=285

krugob8w

krugob8w5#

与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在前一个观察对象完成之前不会订阅下一个观察对象,所以延迟2000毫秒的源值将首先发出。与此相反,mergeMap立即订阅内部观察对象,延迟较小(1000毫秒)的观察对象将发出,然后是需要2000毫秒才能完成的观察对象。

相关问题