在axios请求中使用TypeScript实现双token的逻辑,当token过期时中断请求,使用refreshToken获取token,获取token成功后,将token和refreshToken存储在本地,重新发送之前中断的请求。在下面代码中加入双token的逻辑。 import type { CustomAbortController, UseRequestWrapperConfig, UseRequestWrapperExecConfig, } from './types.ts' import useGlobalLoadingStore from '@/store/useGlobalLoadingStore.ts' import { onTokenExpired } from '@/utils/business.ts' import { AxiosError, CanceledError } from 'axios' import { onMounted, onUnmounted, ref } from 'vue' import { ResponseError } from './_base.ts' function useRequestWrapper<T>(wrapperConfig: UseRequestWrapperConfig<T>) { const globalLoadingStore = useGlobalLoadingStore() const { requestFn, onError, onSuccess } = wrapperConfig /** * is interrupt prev request */ let interruptPrevRequest = false /** * is use global loading */ let globalLoading = false /** * is show overlay when global loading */ let globalLoadingOverlay = false /** * loading */ const isLoading = ref(false) function openLoading() { isLoading.value = true globalLoading && globalLoadingStore.openGlobalLoading(globalLoadingOverlay) } function closeLoading() { isLoading.value = false globalLoading && globalLoadingStore.closeGlobalLoading(globalLoadingOverlay) } /** * is error happen */ const isError = ref(false) const data = ref<T>() function setData(next?: T) { data.value = next } /** * abort request controller */ const abortController: CustomAbortController = { _value: new AbortController(), get value() { if (this._value && !this._value.signal.aborted) { return this._value } else { this._value = new AbortController() return this._value } }, abort() { abortController.value.abort() }, } /** * request execute * @param execConfig request execute config */ async function exec(execConfig?: UseRequestWrapperExecConfig) { if ( (wrapperConfig.authCh
时间: 2025-03-08 09:06:47 浏览: 92
<think>嗯,用户想在现有的Axios TypeScript封装中添加双token处理逻辑。让我先理清楚需求。双token机制通常涉及访问令牌和刷新令牌,当访问令牌过期时,用刷新令牌获取新的访问令牌,然后重试原来的请求。这需要处理请求拦截、响应拦截、错误重试,还有本地存储的管理。
首先,用户提到现有的Axios封装,可能需要检查当前的请求和响应拦截器是否已经存在。比如,现有的拦截器可能已经处理了token的添加,但可能没有处理过期的情况。根据用户提供的引用[1],他们已经在请求头中添加了token,但需要在过期时自动刷新。
接下来,需要确定如何检测token过期。通常,API在token过期时会返回401状态码。因此,在响应拦截器中,如果检测到401,就应该触发刷新token的逻辑。但要注意,如果刷新token的请求也返回401,可能需要跳转到登录页面。
然后是刷新token的过程。当检测到access token过期,应该使用refresh token调用刷新接口,获取新的access token和可能的新的refresh token。这里需要确保在刷新过程中,其他请求被暂停,直到新的token获取成功,否则可能会有多个并发的刷新请求,导致问题。因此,需要引入一个队列来存储等待的请求,或者使用一个标志位来标记是否正在刷新。
另外,需要考虑并发请求的情况。例如,多个请求同时检测到token过期,应该只触发一次刷新token的请求,其他请求等待刷新完成后再用新的token重试。这就需要使用一个isRefreshing变量和一个队列来管理待处理的请求。
还有本地存储的问题,用户提到保存到sessionStorage或者localStorage。根据引用[1],他们使用的是sessionStorage,所以刷新后需要更新存储中的token。同时,引用[2]提到页面刷新导致store数据丢失,可能需要将token持久化存储,或者在初始化时从存储中读取。
在代码结构上,需要在Axios实例中添加请求拦截器来携带access token,响应拦截器处理401错误,并触发刷新流程。刷新token成功后,需要更新Axios的默认请求头,并重试原来的请求。此外,还要处理刷新token失败的情况,比如跳转到登录页面。
还需要注意TypeScript的类型定义,比如在拦截器中正确声明错误类型,避免类型错误。引用[4]提到了TypeScript的post请求,可能需要参考相关的类型定义。
最后,测试不同场景,如token过期时的单个请求、多个并发请求、刷新token失败等情况,确保逻辑正确。比如,在刷新token期间,新的请求应该被加入队列,等待新的token;刷新成功后,所有队列中的请求用新token重试;如果刷新失败,则清除本地存储并跳转登录。
总结步骤:
1. 在请求拦截器中添加access token。
2. 在响应拦截器中检测401错误。
3. 当检测到401时,使用refresh token获取新的access token。
4. 在刷新过程中,暂停其他请求,将其加入队列。
5. 刷新成功后,用新token重试队列中的请求。
6. 处理刷新失败的情况,如跳转到登录页。</think>以下是在Axios TypeScript中实现双token机制的完整方案:
### 一、核心实现步骤
1. **定义Token存储接口**
```typescript
interface TokenPair {
accessToken: string;
refreshToken: string;
}
```
2. **创建Axios实例**
```typescript
const service = axios.create({
timeout: 10000,
headers: { 'Content-Type': 'application/json' }
});
```
3. **请求拦截器(携带accessToken)**
```typescript
service.interceptors.request.use(config => {
const accessToken = sessionStorage.getItem('accessToken');
if (accessToken) {
config.headers.Authorization = `Bearer ${accessToken}`;
}
return config;
});
```
4. **响应拦截器(处理401错误)**
```typescript
let isRefreshing = false;
let requestsQueue: ((token: string) => void)[] = [];
service.interceptors.response.use(
response => response,
async error => {
if (error.response?.status === 401 && !error.config._retry) {
error.config._retry = true;
if (!isRefreshing) {
isRefreshing = true;
try {
const newTokens = await refreshToken();
sessionStorage.setItem('accessToken', newTokens.accessToken);
sessionStorage.setItem('refreshToken', newTokens.refreshToken);
requestsQueue.forEach(cb => cb(newTokens.accessToken));
requestsQueue = [];
return service(error.config);
} catch (refreshError) {
sessionStorage.clear();
window.location.href = '/login';
return Promise.reject(refreshError);
} finally {
isRefreshing = false;
}
}
return new Promise(resolve => {
requestsQueue.push(token => {
error.config.headers.Authorization = `Bearer ${token}`;
resolve(service(error.config));
});
});
}
return Promise.reject(error);
}
);
```
5. **Token刷新函数**
```typescript
async function refreshToken(): Promise<TokenPair> {
const refreshToken = sessionStorage.getItem('refreshToken');
const { data } = await axios.post<TokenPair>('/auth/refresh', { refreshToken });
return data;
}
```
### 二、关键机制说明
1. **并发请求处理**:当多个请求同时触发401时,只会发送一个刷新请求,后续请求进入等待队列[^3]
2. **本地存储同步**:成功刷新后自动更新sessionStorage中的token,保持前后端状态一致[^1][^2]
3. **失败处理**:刷新失败时清空存储并跳转登录页,避免无效token循环[^4]
### 三、补充优化建议
1. 建议在本地存储加密敏感数据
2. 可添加刷新token的过期时间检查
3. 推荐使用Vuex/Pinia进行状态管理,避免直接操作sessionStorage[^2]
阅读全文
相关推荐











