Как вы превращаете эпопею в асинхронную функцию? - PullRequest
0 голосов
/ 07 мая 2019

Следующий код работает без ошибок:

export const myEpic = (action$: any) => action$.pipe(
   ofType("TEST"),
   mergeMap(() => concat(
      // fires an actionCreator and triggers another epic
      of(actionOne()),
      // fires an actionCreator
      of(actionTwo())
   ))
);

Проблема в том, что мне нужно, чтобы данные из actionOne были доступны до того, как actionTwo будет запущен, а этого, похоже, не происходит. Поэтому я хочу сделать это асинхронной функцией, например:

export const myEpic = (action$: any) => action$.pipe(
   ofType("TEST"),
   mergeMap(async () => concat(
      of(await actionOne()),
      of(actionTwo())
   ))
);

Это выдает ошибку:

Uncaught Error: Actions must be plain objects. Use custom middleware for async actions.

EDIT

Другой соответствующий код:

// main component that loads
constructor(props) {
   props.dispatch(init());
}
componentDidUpdate(prevProps) {
   if (prevProps.actionTwoFlag !== this.props.actionTwoFlag) {
      // do stuff with result from actionOne
      // error is thrown here because there's no data
   }
}

// actions
export const init = () => ({ type: "TEST" });
export const actionOne = () => ({ type: "ACTION_ONE" });
export const actionOneDone = (result) => ({ type: "ACTION_ONE_DONE", payload: result });
export const actionTwo = () => ({ type: "ACTION_TWO", payload: true });

// epics
export const actionOneEpic = (action$: any) => action$.pipe(
   ofType("ACTION_ONE"),
   mergeMap(() =>
      ajax(..).pipe(
         mergeMap(result => concat(
            of(actionOneDone(result)),
            ...
         ))
      )
   )
);
);

1 Ответ

0 голосов
/ 07 мая 2019

Существуют различные способы решения этой проблемы.

1- Один из способов - просто использовать оператор defer () в actionTwo.Оператор defer () должен выполнить: выполнить ваш код по подписке , так как они объединены, подписка на of (actionTwo ()) будет выполнена после того, как of (actionOne ()) будет завершена:

export const myEpic = (action$: any) => action$.pipe(
   ofType("TEST"),
   mergeMap(() => concat(
      of(actionOne()),
      defer(() => of(actionTwo()))
   ))
);

2- Другой вариант - это просто сделать switchMap () , это также гарантирует, что когда вы создаете наблюдаемую из (actionTwo ()),(actionOne ()) наблюдаемый уже был отправлен и завершен.switchMap () также обеспечивает последовательный порядок , поэтому вы можете безопасно удалить оператор concat ():

    export const myEpic = (action$: any) => action$.pipe(
       ofType("TEST"),
       mergeMap(() => 
          of(actionOne()).pipe(switchMap(() => of(actionTwo())))
       )
    );

EDIT :

Теперь якажется, я понял, хотя, я не очень хорошо знаком с наблюдаемыми эпопеями.Я видел здесь решение: Составление и секвенирование нескольких эпопей в наблюдаемом редуксе , которые могут решить вашу проблему два.Исходя из этого, я дам 2 предложения.

1-е предложение:

Это предложение просто создает эпос, который сначала подталкивает действие, и ждет действия, которое уже выполнено.чтобы продвинуть действие два.

export const myEpic = (action$: any) => action$.pipe(
    ofType('TEST'),
    map(() => actionOne()),
    mergeMap(() => {
        return action$.pipe(
            ofType('ACTION_ONE_DONE'),
            take(1),
            map(() => actionTwo()),
        );
    })
);

2-е предложение:

Сделай все это в одном эпосе.Поскольку и действие одно, и действие два связаны (одно зависит друг от друга), может иметь смысл объединить оба в один эпос, это будет примерно так:

export const myEpic = (action$: any) => action$.pipe(
    ofType('TEST'),
    map(() => actionOne()),
    mergeMap(() => {
        return ajax(..).pipe(
            mergeMap((data) => {
                return concat(
                    actionOneDone(action),
                    of(actionTwo()).mergeMap(() => /* Do action two */ actionTwoDone())
                )
            }),
        )
    })
);

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...