我在 React Native 应用程序中遇到了令牌管理问题。当令牌过期并且发出多个并行请求时,它们都会尝试刷新令牌。第一个请求成功,但后续请求失败,并出现“已撤销刷新令牌”错误,因为它们使用了过期的令牌。
以下是相关代码片段:
let refreshTokenPromise: Promise<string> | null = null;
const refreshAuthToken = async () => {
if (!refreshTokenPromise) {
refreshTokenPromise = getCredentials().finally(() => {
refreshTokenPromise = null;
});
}
return await refreshTokenPromise;
};
// ... axiosInstance setup ...
const getCredentials = useCallback(async () => {
const currentUnixTimestamp = moment().unix();
if (userAccess.expirationTimeStamp < currentUnixTimestamp) {
console.log('refreshing token', userAccess.accessObject?.refreshToken);
return await refreshToken();
}
return userAccess.accessObject?.accessToken || '';
}, [userAccess, refreshToken]);
以下是指示问题的日志:
LOG getting new token
LOG refreshing token XXXX
LOG getting new token
LOG refreshing token XXXX
我预计 getCredentials 函数在令牌过期后发出多个请求时仅执行一次。然而,正如日志所示,它被多次调用。
我尝试使用 Axios 拦截器在进行 API 调用之前检索凭据,但这种方法也导致了相同的竞争条件。
我已经看到使用像我这样的方法来解决类似的问题来防止竞争条件,但由于某种原因,它在我的情况下不起作用。
任何解决此问题的建议或见解将不胜感激!
SWR例如通过关键参数缓存请求以删除请求的重复数据
示例:https://github.com/vercel/swr/blob/main/examples/basic/pages/index.js
import Link from 'next/link'
import fetch from '../libs/fetch'
import useSWR from 'swr'
export default function Index() {
const { data } = useSWR('/api/data', fetch) // First parameter is the request key which will prevent to execute several times
return (
<div style={{ textAlign: 'center' }}>
<h1>Trending Projects!</h1>
<div>
{
data ? data.map(project =>
<p key={project}><Link href='/[user]/[repo]' as={`/${project}`}>{project}</Link></p>
) : 'loading...'
}
</div>
</div>
)
}