22 votes

envoi de plusieurs actions en un effet

Je voudrais diapatch deux actions en un effet. Actuellement, j'ai à déclarer deux effets pour obtenir ceci :

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

Est-il possible d'avoir une action, être à l'origine de deux actions par le biais d'un seul effet ?

34voto

Javier González Points 550
@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
                    })
                )
            )
    );

8voto

Maxime Points 1054

Vous pouvez utiliser switchMap et Observable.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
    }));

Des questions de rendement :

Plutôt que de solliciter de nombreuses actions qui vont déclencher toutes les abonnés autant de fois que vous l'expédition, vous pouvez prendre un coup d'oeil dans redux-par lot-actions.

Cela vous permet de vous avertir de vos abonnés uniquement lorsque toutes ces multiples actions ont été appliquées à la boutique.

Par exemple :

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

4voto

Victor Godoy Points 993

Vous pouvez choisir mergeMap pour async ou concatMap pour la synchronisation

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

2voto

JusMalcolm Points 1097

vous pouvez également utiliser .n'() et de les stocker.next()

ne vous permet de l'attacher à un rappel à l'observable sans affecter les autres opérateurs / modifier le observables

par exemple

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

(vous aurez besoin d'une référence pour le magasin de votre effets de classe)

2voto

Yaremenko Andrii Points 141

Si quelqu'un se demande comment mélanger la plaine des actions avec ceux d'Observables.

J'étais coincé avec la même tâche, mais petite différence: j'ai besoin d'envoi de deux actions, avec une seconde après appel d'API, ce qui en fait un Observable. Quelque chose comme:

  1. action1 est juste une action: {type: 'ACTION_ONE'}
  2. action2 est appel API mappé à l'action: Observable<{type: 'ACTION_TWO'}>

Code suivant résolu mon problème:

@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 du doc

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X