我正在尝试将我的executeWithRetries
实用程序(参见下文)升级到redux-observable
的最新版本,在该版本中,不再允许在史诗中进行分派。
[当前,该实用程序查看所需令牌是否已过期,如果已过期,它将调度REFRESH_TOKEN
操作并返回新的action$
,该新C [0]通过执行原始请求来响应所产生的REFRESH_TOKEN_SUCCESS
操作,并使用新的包含令牌。这可以正常工作。
没有显式分派动作,我怎么都可以:
REFRESH_TOKEN
操作和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
兼容,但是我不知道这种情况下的替代方法。
事实证明,您可以通过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的依赖项之一注入。