在前端应用中,常常需要处理因token过期而导致的请求失败的情况。我们可以将这些失败的请求挂起,待token刷新成功后重试这些请求。以下是一个实现细节:
基本思路
- 拦截请求失败: 使用请求库(如Axios)拦截请求错误,判断是否因token过期而失败。
- 存储挂起请求: 将这些请求存储在一个数组中,以便在token刷新成功后重试。
- 刷新token: 当检测到token过期时,触发刷新token的请求。
- 重试挂起请求: 在token刷新成功后,重新发送挂起的请求。
实现步骤
以下是一个使用Axios的示例:
import axios from 'axios';
// 创建一个Axios实例
const apiClient = axios.create();
// 挂起请求的数组
let pendingRequests = [];
// 是否正在刷新token
let isRefreshing = false;
// 请求拦截器,添加token到请求头
apiClient.interceptors.request.use(config => {
const token = localStorage.getItem('access_token');
if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
}
return config;
}, error => {
return Promise.reject(error);
});
// 响应拦截器,处理token过期
apiClient.interceptors.response.use(response => {
return response;
}, error => {
const { config, response } = error;
const originalRequest = config;
// 检查是否是token过期错误(假设401表示过期)
if (response && response.status === 401) {
// 如果已经在刷新token,将请求挂起
if (isRefreshing) {
return new Promise((resolve, reject) => {
pendingRequests.push({ resolve, reject });
}).then(token => {
originalRequest.headers['Authorization'] = `Bearer ${token}`;
return axios(originalRequest);
}).catch(err => {
return Promise.reject(err);
});
}
// 开始刷新token
isRefreshing = true;
return new Promise((resolve, reject) => {
refreshToken() // 假设一个刷新token的方法
.then(newToken => {
localStorage.setItem('access_token', newToken);
apiClient.defaults.headers['Authorization'] = `Bearer ${newToken}`;
originalRequest.headers['Authorization'] = `Bearer ${newToken}`;
// 重新发送所有挂起的请求
pendingRequests.forEach(req => {
req.resolve(newToken);
});
pendingRequests = [];
resolve(axios(originalRequest));
})
.catch(err => {
pendingRequests.forEach(req => {
req.reject(err);
});
pendingRequests = [];
reject(err);
})
.finally(() => {
isRefreshing = false;
});
});
}
return Promise.reject(error);
});
// 模拟刷新token的函数
function refreshToken() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const newToken = 'new-token-value'; // 假设获得了新token
resolve(newToken);
}, 1000);
});
}
说明
- 挂起请求: 当检测到token过期,且当前正在刷新token时,将请求存储在
pendingRequests
数组中。 - 刷新token过程: 当刷新token成功后,遍历
pendingRequests
数组,使用新的token重试请求。 - 状态管理: 使用
isRefreshing
标志来避免同时发起多个token刷新请求。
这个实现确保了API请求在token过期时不会被丢弃,而是等待token刷新后继续执行。根据实际需求,你可能需要调整token存储和获取的方式