在Redux Observable/RxJS中,如何发出动作和助手函数的组合

在Redux Observable/RxJS中,如何发出动作和助手函数的组合,rxjs,redux-observable,Rxjs,Redux Observable,用户通过身份验证后,我需要调用2个函数(AsyncStorage.setItem和setapiaAuthorization),然后调用2个redux操作(LOAD\u user和SET\u SESSION\u user)。根据下面的尝试,我将如何实现这一点?或者我也应该为这两个函数创建redux操作 const loginUserEpic = (action$, state$) => action$.pipe( ofType('LOGIN_USER'), mergeMa

用户通过身份验证后,我需要调用2个函数(
AsyncStorage.setItem
setapiaAuthorization
),然后调用2个redux操作(
LOAD\u user
SET\u SESSION\u user
)。根据下面的尝试,我将如何实现这一点?或者我也应该为这两个函数创建redux操作

const loginUserEpic = (action$, state$) =>
  action$.pipe(
    ofType('LOGIN_USER'),
    mergeMap(() =>
      from(axios.post(`/auth`, {})).pipe(
        mergeMap(response =>
          of(
            AsyncStorage.setItem('id_token', response.data.token),
            setAPIAuthorization(response.data.token),
            {
              type: 'LOAD_USER'
            },
            {
              type: 'SET_SESSION_USER',
              user: response.data.user
            }
          )
        ),
        catchError(error => console.log(error))
      )
    )
  );
感谢下面的Anas,这里是我用来实现我想要的更新。到目前为止取得了成功。在我存储
id\u令牌之后,它将包含在任何后续api调用的头中。因此,我需要确保在调用作为api调用的
LOAD\u USER
之前保存
id\u令牌

const loginUserEpic = (action$, state$) =>
  action$.pipe(
    ofType('LOGIN_USER'),
    mergeMap(() =>
      from(axios.post(`/auth`, {})).pipe(
        mergeMap(response => {
          return new Observable(observer => {
            AsyncStorage.setItem('id_token', response.data.token);
            setAPIAuthorization(response.data.token);
            observer.next(
              {
                type: 'LOAD_USER'
              },
              {
                type: 'SET_SESSION_USER',
                user: response.data.user
              }
            );
          });
        }),
        catchError(error => console.log(error))
      )
    )
  );

设置会话存储是一个副作用。 所以最好在一个

您的epic应该只将动作作为输出返回(动作输入、动作输出)。如果您这样做,redux会抱怨您没有返回简单的操作

我仍然会为
{type:'LOAD_USER'}
{type:'SET_SESSION_USER'}
创建操作创建者,因为它更干净

const loginUserEpic = (action$, state$) =>
  action$.pipe(
    ofType('LOGIN_USER'),
    mergeMap(() =>
      from(axios.post('/auth', {})).pipe(
        tap((response) => {
          AsyncStorage.setItem('id_token', response.data.token)
          setAPIAuthorization(response.data.token)
        }),
        mergeMap(response =>
          of(
            {
              type: 'LOAD_USER',
            },
            {
              type: 'SET_SESSION_USER',
              user: response.data.user,
            }
          )
        ),
        catchError(error => console.log(error))
      )
    )
  )

另一个简单的方法是使用
switchMap

switchMap(() => [
  {
    type: 'LOAD_USER',
                },
  {
    type: 'SET_SESSION_USER',
    user: response.data.user,
  }
])

只要结果是一个数组,它就会自动将结果包装成可观察值。因此,您不再需要
of()
它。我在项目中经常使用它。

谢谢。请问,在调用
mergeMap
之前,
点击是否完成?在
LOAD\u USER
操作中需要保存到存储中的
id\u令牌
,因此我需要确保在调用
LOAD\u USER
@theseboys之前始终保存该令牌。
tap
不能保证在
mergeMap
启动之前完成。为了实现这种行为,您需要将
AsyncStorage.setItem
包装在一个可观察的文件中。但不管怎样,我认为访问reducer中的
存储
不是一个好主意,因为你会给你的reducer带来副作用,这应该是纯的。更好的方法是将响应传递给您的操作
{type:'LOAD\u USER'}
,并在减速器中使用它,而不引入副作用。谢谢。我在开场白中添加的最新史诗看起来如何?