在我的应用中,我正在通过api中间件运行每个请求。当使用Authorization的请求发生且令牌已过期时,我正在尝试创建中间件重试功能。这是我当前的API中间件:
const apiMiddleware = ({ dispatch }) => next => action => {
next(action);
// creating request data and params
const retryRequest = () => {
// refresh tokens with method: dispatch(getTokens());
// retry initial request
};
axios({
method,
url,
headers,
[dataOrParams]: data,
})
.then(({ data: apiData }) => {
dispatch(onSuccess(apiData));
})
.catch(error => {
if (withToken && error.response.status === 401) {
retryRequest();
}
return dispatch(apiError(label, error));
})
};
export default apiMiddleware;
当我调用retryRequest()
方法时,getTokens()
请求启动,但同时启动了初始请求,并且Redux尚未使用新的刷新令牌进行更新,并且请求再次失败,因为getTokens()
尚未完成。
我知道我做错了方法,我还能尝试其他解决方案吗?因此,首先调用并完成请求getTokens()
才能完成初始请求。
如果可以使retryRequest()和catch函数异步,则可以使用
if(withToken && error.reponse.status === 401)
await retryRequest();
return dispatch(apiError(label, error));
如果不能,则从重试请求中返回承诺,然后
if(withToken && error.response.status === 401)
return retryRequest().then(_=> dispatch(apiError(label, error)))
return dispatch(apiError(label, error))
您还可以使用axios拦截器,这是我在最近的项目中使用的那个
api.interceptors.response.use(
function (response) {
response.data = parseResponseData(response.data);
return response;
},
async function (error) {
if (!error.response)
Ant.message.error('Não foi possivel se conectar com o servidor');
else if (
error.response.status === 500 &&
window.location.pathname !== '/erro/500'
) {
if ((error.config.method as string).toLowerCase() === 'get')
navigate('/erro/500');
else
Ant.message.error(
'Desculpe, parece que algo deu errado no servidor.',
);
} else if (error.response.status === 401) {
let request = error.config;
const auth = localStorage.getItem('auth');
let refreshToken = auth && JSON.parse(auth)['refreshToken'];
var authService = new AuthService();
return await authService
.refresh(refreshToken)
.then(async (resp) => {
store.dispatch(login(resp.data));
let axiosInstance = axios.create();
intercept(axiosInstance);
return await axiosInstance.request(request);
})
.catch((e) => {
if (
window.location.pathname !== '/login' &&
(!e.response || e.response.status === 401)
)
navigate('/login');
});
}
return error.response;
},
);
到目前为止,效果很好。