javascript
复制代码
import { apiUrl } from '@/config/global-config.js'
import { useUserStore } from '../stores'
import { usePageRoute } from "@/composable/usePageRoute.js"
// 默认配置
const DEFAULT_CONFIG = {
timeout: 60000,
// showLoading: true,
// loadingText: '加载中...'
}
// 添加刷新token的方法
const refreshToken = async () => {
const userStore = useUserStore()
try {
const response = await uni.request({
url: apiUrl + '/auth/refresh', // 替换成你的刷新token接口
method: 'POST',
header: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${userStore.token}`
}
})
if (response.data.code === 200) {
userStore.setToken(response.data.data.token)
return true
}
return false
} catch (error) {
return false
}
}
// 添加一个变量来存储刷新token的Promise
let isRefreshing = false
let refreshSubscribers = []
// 执行等待的请求
const onRefreshed = (token) => {
refreshSubscribers.forEach(callback => callback(token))
refreshSubscribers = []
}
// 添加请求到队列
const addSubscriber = (callback) => {
refreshSubscribers.push(callback)
}
// 请求拦截器
const requestInterceptor = (config) => {
const userStore = useUserStore()
const token = userStore.token
const isMapApi = /apis\.map\.qq\.com/.test(config.url)
if (token && !isMapApi) {
config.header.Authorization = `Bearer ${token}`
}
// if (config.showLoading) {
// uni.showLoading({ title: config.loadingText })
// }
return config
}
// 响应拦截器
const responseInterceptor = async (response) => {
const userStore = useUserStore()
// const { code, msg, data } = response.data
const code = response.data.code
const msg = response.data.msg
const data = response.data
// const data = response.data.data
// console.log(data,code,msg);
switch (code) {
case 200:
return data
// return Promise.resolve(data)
case 401: {
// 如果是刷新token的请求失败,直接登出
if (config.url.includes('/auth/refresh')) {
await handleLogout()
return Promise.reject(new Error('登录已失效'))
}
// 处理token刷新
if (!isRefreshing) {
isRefreshing = true
try {
const refreshResult = await refreshToken()
if (refreshResult) {
const newToken = userStore.token
onRefreshed(newToken)
// 重试当前请求
config.header.Authorization = `Bearer ${newToken}`
return request(config)
} else {
await handleLogout()
return Promise.reject(new Error('登录已失效'))
}
} finally {
isRefreshing = false
}
}
// 返回一个Promise,将请求暂存
return new Promise((resolve) => {
addSubscriber((token) => {
config.header.Authorization = `Bearer ${token}`
resolve(request(config))
})
})
// 上面是刷新token 如果没有刷新token的接口直接登出 把上面的401代码注释 解开下面的两行注释
//await handleLogout()
//return Promise.reject(new Error('登录已失效'))
}
default:
uni.showToast({
icon: 'none',
title: msg || '请求错误',
duration: 2000
})
return Promise.reject(new Error(msg || '请求错误'))
}
}
// 添加统一的登出处理方法
const handleLogout = async () => {
const userStore = useUserStore()
const pageRoute = usePageRoute()
const fullPagePath = pageRoute.getCurrentFullPagePath()
uni.setStorageSync('fullPage', fullPagePath)
uni.$msgBox('登录已失效,请重新登录', 2000)
userStore.clearToken()
userStore.clearUser()
await uni.$delay(2000)
uni.reLaunch({ url: '/pages/login/login' })
}
// 统一请求方法
const request = (options = {}) => {
const config = {
...DEFAULT_CONFIG,
...options,
header: {
'Content-Type': 'application/json',
...options.header
}
}
config.url = apiUrl + config.url
// 应用请求拦截器
const interceptedConfig = requestInterceptor(config)
return new Promise((resolve, reject) => {
uni.request({
...interceptedConfig,
success: async (res) => {
try {
const result = await responseInterceptor(res)
resolve(result)
} catch (error) {
reject(error)
}
},
fail: (error) => {
uni.showToast({
icon: 'none',
title: '网络错误,请检查网络连接',
duration: 2000
})
reject(error)
},
complete: () => {
// if (config.showLoading) {
// uni.hideLoading()
// }
}
})
})
}
// 导出请求方法
export const $get = (url, data, options = {}) => {
return request({
url,
data,
method: 'GET',
...options
})
}
export const $post = (url, data, options = {}) => {
return request({
url,
data,
method: 'POST',
...options
})
}
// 挂载到全局
uni.$get = $get
uni.$post = $post