如何在不中断异步流的情况下自动刷新 redux 中的 JWT?



高级描述

我有一个使用 Google Oauth 的 React/redux/electron 应用程序。我希望能够在访问令牌过期时自动刷新访问令牌。我已经对此进行了研究,并使用中间件半成功地解决了它,但是我的解决方案在某些情况下出错了。

我已经实现了一个在每个 API 操作上运行的刷新中间件。它检查访问令牌是否已过期或即将过期。如果是这样,它不会调度它收到的操作,而是调度令牌刷新操作并将任何其他操作排队,直到收到新的访问令牌。之后,它会调度队列中的所有操作。

但是,我的一个动作创作者看起来像这样:

function queryThreads(params) {
return async (dispatch) => {
const threads = await dispatch(fetchThreads(params))
const newPageToken = threads.payload.nextPageToken
}
}

当刷新中间件由于令牌未过期而未运行时,将在此处定义threads.payload,并且一切都将按预期工作。

但是,当刷新中间件运行时,threads.payload将被undefined,因为dispatch似乎使用令牌刷新操作的值而不是fetchThreads操作进行解析。

如何确保令牌被刷新(并在state/localStorage中更新(,fetchThreads使用更新的令牌进行调度,并且threads变量被分配给正确 Promise 的解析值?

指向项目代码的链接

这是我的刷新中间件。它的灵感来自kmmbvnr的这篇文章。

这是令牌刷新操作创建程序。

这是我的 queryThreads 操作创建器中的行,当令牌必须刷新时抛出(threads.payloadundefined(。

这是我更新状态以响应令牌刷新的化简器。

这是我更新本地存储以响应令牌刷新的中间件。

看起来我已经通过像这样重写刷新中间件解决了这个问题:

function createRefreshMiddleware() {
const postponedRSAAs = [];
return ({ dispatch, getState }) => {
const rsaaMiddleware = apiMiddleware({ dispatch, getState });
return next => action => {
if (isRSAA(action)) {
try {
const auth = JSON.parse(localStorage.getItem('auth'));
const { refresh_token: refreshToken } = auth;
const expirationTime = jwtDecode(auth.id_token).exp * 1000;
const isAccessTokenExpiring =
moment(expirationTime) - moment() < 300000;
if (refreshToken && isAccessTokenExpiring) {
postponedRSAAs.push(action);
if (postponedRSAAs.length === 1) {
return rsaaMiddleware(next)(
dispatch(() => attemptTokenRefresh(refreshToken))
).then(() => {
const postponedRSAA = postponedRSAAs.pop();
return dispatch(postponedRSAA);
});
}
return rsaaMiddleware(next)(action);
}
return rsaaMiddleware(next)(action);
} catch (e) {
console.log(e);
return next(action);
}
}
return next(action);
};
};
}
export default createRefreshMiddleware();

现在,推迟的操作将始终与令牌刷新操作链接,因此我们没有原始承诺使用错误值解析的问题;而且它更简洁。

相关内容

  • 没有找到相关文章

最新更新