我如何在Redux可观察的同一史诗中发出动作和流?

问题描述 投票:0回答:1

我正在尝试将我的executeWithRetries实用程序(参见下文)升级到redux-observable的最新版本,在该版本中,不再允许在史诗中进行分派。

[当前,该实用程序查看所需令牌是否已过期,如果已过期,它将调度REFRESH_TOKEN操作并返回新的action$,该新C [0]通过执行原始请求来响应所产生的REFRESH_TOKEN_SUCCESS操作,并使用新的包含令牌。这可以正常工作。

没有显式分派动作,我怎么都可以:

  1. 同时触发REFRESH_TOKEN操作和
  2. 创建一个响应另一个(结果)动作的流?
import {isEmpty} from 'ramda';
import { of } from 'rxjs/observable/of';
import {
  actions as guestActions,
  selectApiKey,
  selectGuestRefreshToken,
  selectGuestTokenExpiryMs,
  types as guestTypes,
} from '../reducers/guest';

const retryOrFail = ({ requestFactory, failure, success, store }) => {
  const state = store.getState();
  const apiKey = selectApiKey(state);
  const tokens = { apiKey, accessToken };
  return requestFactory.retry(tokens)
    .map(res => {
      return success(res);
    })
    .catch(err => {
      return retryOrFail({ requestFactory, failure, success, store });
    });
};

const refreshTokensIfNecessary = (store) => {
  const state = store.getState();
  const guestRefreshToken = selectGuestRefreshToken(state);
  const guestTokenExpiryMs = selectGuestTokenExpiryMs(state);
  const { dispatch } = store;

  const guestTokenExpired = () => guestRefreshToken && guestTokenExpiryMs && guestTokenExpiryMs < Date.now();

  if (guestTokenExpired()) {
    dispatch(guestActions.refreshToken(guestRefreshToken));
    return true;
  }
  return false;
}

export default function executeWithRetries({ requestFactory, success, failure, store, action$ }) {
  const retryAction = action$.ofType(
    guestTypes.REFRESH_TOKEN_SUCCESS
  )
    .take(1)
    .switchMap(() => retryOrFail({ requestFactory, failure, success, store }));

  if (refreshTokensIfNecessary(store)) {
    return retryAction;
  }

  return requestFactoryToUse.execute()
    .map(res => success(res))
    .catch((err) => {
      return of(failure(err.toString()));
    });
}

[可能是因为该代码依赖于分派动作,所以该代码的结构不再与redux-observable@latest兼容,但是我不知道这种情况下的替代方法。

rxjs redux-observable
1个回答
0
投票

事实证明,您可以通过dispatch手动将store包括在史诗的依赖项中,并在必要时绕开史诗中对dispatch的禁止。

示例:

const configureStore = () => {
  const store = createStore(
    rootReducer,
    composeEnhancers(applyMiddleware(epicMiddleware)),
  );
  epicMiddleware.run(rootEpic, {
    dependencies: {
      fetch,
      dispatch: store.dispatch,
    },
  });
  return store;
};

(下面的史诗样本最好与mapTo搭配使用,但证明了这种可能性:

export const CancelOrder = (action$, store, { dispatch }) => action$
  .pipe(
    ofType(types.CANCEL_ORDER),
    tap(() => dispatch(cancelRequestAction)),
    ignoreElements()
  );

在我的情况下,为避免我的请求实用程序中出现大的卷积,我将dispatch作为epicMiddleware的依赖项之一注入。

© www.soinside.com 2019 - 2024. All rights reserved.