在一个效果中调度多个动作

时间:2017-01-17 15:35:15

标签: angular redux ngrx

我想在一个效果中发送两个动作。 目前我必须声明两种效果来实现这一目标:

  // first effect
  @Effect() action1$ = this.actions$
    .ofType(CoreActionTypes.MY_ACTION)
    .map(res => {
      return { type: "ACTION_ONE"}
    })
    .catch(() => Observable.of({
      type: CoreActionTypes.MY_ACTION_FAILED
    }));

  // second effect
  @Effect() action2$ = this.actions$
    .ofType(CoreActionTypes.MY_ACTION)
    .map(res => {
      return { type: "ACTION_TWO"}
    })
    .catch(() => Observable.of({
      type: CoreActionTypes.MY_ACTION_FAILED
    }));

是否可以通过单一效果成为一个动作的源头?

6 个答案:

答案 0 :(得分:35)

@Effect()
loadInitConfig$ = this.actions$
    .ofType(layout.ActionTypes.LOAD_INIT_CONFIGURATION)
    .map<Action, void>(toPayload)
    .switchMap(() =>
        this.settingsService
            .loadInitConfiguration()
            .mergeMap((data: any) => [
                new layout.LoadInitConfigurationCompleteAction(data.settings),
                new meetup.LoadInitGeolocationCompleteAction(data.geolocation)
            ])
            .catch(error =>
                Observable.of(
                    new layout.LoadInitConfigurationFailAction({
                        error
                    })
                )
            )
    );

答案 1 :(得分:9)

您可以使用switchMapObservable.of

 @Effect({ dispatch: true }) action$ = this.actions$
    .ofType(CoreActionTypes.MY_ACTION)
    .switchMap(() => Observable.of(
        // subscribers will be notified
        {type: 'ACTION_ONE'} ,
        // subscribers will be notified (again ...)
        {type: 'ACTION_TWO'}
    ))
    .catch(() => Observable.of({
      type: CoreActionTypes.MY_ACTION_FAILED
    }));

效果重要:

您可能需要查看redux-batched-actions,而不是发送许多触发所有订阅者的动作的行动。

这允许您仅在所有这些多个操作都应用于商店时警告您的订阅者。

例如:

@Effect({ dispatch: true }) action$ = this.actions$
    .ofType(CoreActionTypes.MY_ACTION)
    // subscribers will be notified only once, no matter how many actions you have
    // not between every action
    .map(() => batchActions([
        doThing(),
        doOther()
    ]))
    .catch(() => Observable.of({
      type: CoreActionTypes.MY_ACTION_FAILED
    }));

答案 2 :(得分:4)

您可以为异步选择mergeMap或同步concatMap

  @Effect() action$ = this.actions$
    .ofType(CoreActionTypes.MY_ACTION)
    .mergeMap(() => Observable.from([{type: "ACTION_ONE"} , {type: "ACTION_TWO"}]))
    .catch(() => Observable.of({
      type: CoreActionTypes.MY_ACTION_FAILED
    }));

答案 3 :(得分:2)

你也可以使用.do()和store.next()

do允许您将回调附加到observable而不影响其他运算符/更改observable

e.g。

@Effect() action1$ = this.actions$
.ofType(CoreActionTypes.MY_ACTION)
.do(myaction => this.store.next( {type: 'ACTION_ONE'} ))
.switchMap((myaction) => Observable.of(
    {type: 'ACTION_TWO'}
))
.catch(() => Observable.of({
  type: CoreActionTypes.MY_ACTION_FAILED
}));

(您需要在效果类中引用商店)

答案 4 :(得分:1)

如果有人想知道如何将简单动作与Observables中的动作混合使用。

我被困在相同的任务上,但差别很小:我需要分派两个动作,第二个动作在API调用之后进行,这使其成为可观察的。像这样:

  1. action1只是一个动作:{type: 'ACTION_ONE'}
  2. action2是API调用映射到操作:Observable<{type: 'ACTION_TWO'}>

以下代码解决了我的问题:

@Effect() action$ = this.actions$.pipe(
    ofType(CoreActionTypes.MY_ACTION),
    mergeMap(res =>
        // in order to dispatch actions in provided order
        concat(
            of(action1),
            action2
        )
    ),
    catchError(() => Observable.of({
        type: CoreActionTypes.MY_ACTION_FAILED
    }))
);

concat doc's

答案 5 :(得分:1)

如何在flatMap8.3.0的ngrx effects版本语法中使用以下actions

  someEffect$ = createEffect(() =>
    this.actions$.pipe(
      ofType(CoreActionTypes.MY_ACTION),
      flatMap((data) => [
        CoreActionTypes.MY_ACTION_2(data),
        CoreActionTypes.MY_ACTION_3(data),
      ])
    )
  );