我想在AXIOS "axios": "^1.3.4",
中在后台刷新令牌,当服务器端返回访问令牌到期时,客户端将请求存储在队列中,并在新令牌刷新后恢复请求.当我使用Promise时,我的react 是这样的:
instance.interceptors.response.use((response:AxiosResponse<any, any>) => {
const originalRequest:InternalAxiosRequestConfig<any> = response.config;
if(isRefreshing){
addRequestToQueue(originalRequest);
}
if (!isRefreshing) {
if(response.data.resultCode === ResponseCode.ACCESS_TOKEN_EXPIRED){
addRequestToQueue(originalRequest);
isRefreshing = true;
// refresh the access token
ResponseHandler.handleWebCommonFailure(response.data)
.then((data:any) => {
isRefreshing = false;
pendingRequestsQueue.forEach((request) => {
const accessToken = localStorage.getItem(WheelGlobal.ACCESS_TOKEN_NAME);
request.resolve(accessToken)
.then((resp:any)=>{
// get the action of original request
const action = request.action;
const data = resp.data.result;
// change the state to make it render the UI
store.dispatch(action(data));
});
});
pendingRequestsQueue = [];
});
}
}
return response;
},
(error: any) => { return Promise.reject(error) }
)
第request.resolve(accessToken)
行显示错误caught (in promise) TypeError: Cannot read properties of undefined (reading 'then')
,这是定义的addRequestToQueue
函数:
function addRequestToQueue(originalRequest: any){
return new Promise((resolve, reject) => {
pendingRequestsQueue.push({ resolve, reject });
})
.then((data:any) => {
originalRequest.headers['x-access-token'] = data.accessToken;
originalRequest.headers['x-request-id'] = uuid();
return instance(originalRequest);
})
.catch((err) => {
return Promise.reject(err);
});
}
我应该做些什么来解决这个问题?这是我的AXIOS客户端的完整代码:
import axios, { AxiosResponse, InternalAxiosRequestConfig } from 'axios';
import { v4 as uuid } from 'uuid';
import store from '../store/store';
import { ResponseCode, ResponseHandler, WheelGlobal } from 'js-wheel';
let isRefreshing = false
let pendingRequestsQueue: Array<any> = [];
const instance = axios.create({
timeout: 60000
})
instance.defaults.headers.post['Content-Type'] = 'application/json'
instance.interceptors.request.use((request) => {
const accessToken = localStorage.getItem(WheelGlobal.ACCESS_TOKEN_NAME);
accessToken && (request.headers['x-access-token'] = accessToken);
request.headers['x-request-id'] = uuid();
return request
},
(error: any) => {
return Promise.reject(error)
}
)
function addRequestToQueue(originalRequest: any): Promise<any> {
return new Promise((resolve, reject) => {
pendingRequestsQueue.push({ resolve, reject });
})
.then((data: any) => {
originalRequest.headers['x-access-token'] = data.accessToken;
originalRequest.headers['x-request-id'] = uuid();
return instance(originalRequest);
})
.catch((err) => {
return Promise.reject(err);
});
}
instance.interceptors.response.use((response: AxiosResponse<any, any>) => {
const originalRequest: InternalAxiosRequestConfig<any> = response.config;
if (isRefreshing) {
addRequestToQueue(originalRequest);
}
if (!isRefreshing) {
if (response.data.resultCode === ResponseCode.ACCESS_TOKEN_EXPIRED) {
addRequestToQueue(originalRequest);
isRefreshing = true;
// refresh the access token
ResponseHandler.handleWebCommonFailure(response.data)
.then((data: any) => {
isRefreshing = false;
pendingRequestsQueue.forEach((request) => {
const accessToken = localStorage.getItem(WheelGlobal.ACCESS_TOKEN_NAME);
const promise = request.resolve(accessToken);
if (promise) {
promise.then((resp: any) => {
// get the action of original request
const action = request.action;
const data = resp.data.result;
// change the state to make it render the UI
store.dispatch(action(data));
});
}
});
pendingRequestsQueue = [];
});
}
}
return response;
},
(error: any) => { return Promise.reject(error) }
)
export function requestWithAction(config: any, action: (arg0: any) => any) {
return instance(config).then(
(response: { data: { result: any; }; }) => {
const data = response.data.result;
store.dispatch(action(data));
return response.data;
}
).catch(
(error: any) => {
console.error(error);
}
);
}