我正在尝试实现以下内容:当API调用导致会话过期时,会弹出一个用户可以填写的模式登录表单。 重新登录后,重试原始请求并从dispatch
结果返回的原始承诺。
到目前为止,我在商店中有一个pendingActions
列表和一个sessionExpired
标志。该标志控制ModalLogin
的挂载,可以调度retryPendingActions
thunk。所以除了正确解决原始承诺之外,一切都有效:
this.props.dispatch(addItem(...)) // Either never resolves, or resolves too early
.then(doStuffWithItem)
.catch(handleUserErrors);
如果我可以在商店中保存承诺,我可以避免在会话过期上解决它,而是在retryPendingActions
期间解决它。但是,我已经阅读了很多问题和官方文档,这是一个坏主意。
我是以错误的方式来做这件事的吗?有没有更好的方法来处理这种情况?
答案 0 :(得分:0)
不确定这是否是最好的答案,但我能够找到答案。它有点hackish,但涉及将subscribe
方法放入thunk:
const store = createStore(
rootReducer,
defaultState,
applyMiddleware(ReduxThunk.withExtraArgument((...args) => store.subscribe(...args)))
);
从那时起,它就是在正确的时间解决承诺:
function retryWhileNotLoggedIn(fetcher, dispatch, getState, subscribe) {
let resolve, reject, unsubscribe;
const ret = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
const attempt = () => fetcher()
.then(resolve, err => {
if (err && err.status === 403) {
unsubscribe = subscribe(onStoreChange);
dispatch(actions.setSessionExpired(true));
} else {
reject(err);
}
});
function onStoreChange() {
if (getState().sessionValid) { // Other checks possible
unsubscribe();
attempt();
}
}
attempt();
return ret;
}
使用retryWhileNotLoggedIn
,包装API本身非常简单:
function getItem(item, metadata={}) {
return function thunk(dispatch, getState, subscribe) {
dispatch(actions.startCall("getItem", metadata));
return retryWhileNotLoggedIn(() => api.getItem(item), dispatch, getState, subscribe)
.then(res => {
dispatch(actions.endCall("getItem", metadata));
return res;
}, err => {dispatch(actions.endCall("getItem"), metadata); throw err;});
};
}
完整实现还有一个额外的检查,以查看登录用户或活动路由是否更改,在这种情况下,承诺未解决。这种方法的一个缺点是挂起的操作不再存储在商店中,而是隐藏在最终归api
模块所拥有的一系列闭包中
答案 1 :(得分:0)
另一个选择是使用redux-observable
。
Here是angular2
的示例