Generating commit message...
This commit is contained in:
230
mini-program/api/request.js
Normal file
230
mini-program/api/request.js
Normal file
@@ -0,0 +1,230 @@
|
||||
import config from './config.js'
|
||||
|
||||
// 请求队列(用于处理token刷新)
|
||||
const requestQueue = []
|
||||
let isRefreshing = false
|
||||
|
||||
class Request {
|
||||
constructor() {
|
||||
this.baseURL = config.baseURL
|
||||
this.timeout = config.timeout
|
||||
this.interceptors = {
|
||||
request: [],
|
||||
response: []
|
||||
}
|
||||
}
|
||||
|
||||
// 添加请求拦截器
|
||||
addRequestInterceptor(interceptor) {
|
||||
this.interceptors.request.push(interceptor)
|
||||
}
|
||||
|
||||
// 添加响应拦截器
|
||||
addResponseInterceptor(interceptor) {
|
||||
this.interceptors.response.push(interceptor)
|
||||
}
|
||||
|
||||
// 执行请求拦截器
|
||||
async runRequestInterceptors(config) {
|
||||
for (const interceptor of this.interceptors.request) {
|
||||
config = await interceptor(config)
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
// 执行响应拦截器
|
||||
async runResponseInterceptors(response) {
|
||||
for (const interceptor of this.interceptors.response) {
|
||||
response = await interceptor(response)
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
// 核心请求方法
|
||||
async request(options) {
|
||||
try {
|
||||
// 合并配置
|
||||
const requestConfig = {
|
||||
url: options.url.startsWith('http') ? options.url : `${this.baseURL}${options.url}`,
|
||||
method: options.method || 'GET',
|
||||
header: {
|
||||
'Content-Type': 'application/json',
|
||||
...options.header
|
||||
},
|
||||
data: options.data,
|
||||
timeout: this.timeout
|
||||
}
|
||||
|
||||
// 执行请求拦截器
|
||||
const finalConfig = await this.runRequestInterceptors(requestConfig)
|
||||
|
||||
// 发起请求
|
||||
const response = await uni.request(finalConfig)
|
||||
|
||||
// 执行响应拦截器
|
||||
const finalResponse = await this.runResponseInterceptors(response)
|
||||
|
||||
return finalResponse[1] // uni.request返回的是数组[error, success]
|
||||
} catch (error) {
|
||||
console.error('Request error:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// GET请求
|
||||
get(url, data = {}, options = {}) {
|
||||
return this.request({
|
||||
url,
|
||||
method: 'GET',
|
||||
data,
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// POST请求
|
||||
post(url, data = {}, options = {}) {
|
||||
return this.request({
|
||||
url,
|
||||
method: 'POST',
|
||||
data,
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// PUT请求
|
||||
put(url, data = {}, options = {}) {
|
||||
return this.request({
|
||||
url,
|
||||
method: 'PUT',
|
||||
data,
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// DELETE请求
|
||||
delete(url, data = {}, options = {}) {
|
||||
return this.request({
|
||||
url,
|
||||
method: 'DELETE',
|
||||
data,
|
||||
...options
|
||||
})
|
||||
}
|
||||
|
||||
// 上传文件
|
||||
upload(url, filePath, formData = {}, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.uploadFile({
|
||||
url: `${this.baseURL}${url}`,
|
||||
filePath,
|
||||
name: 'file',
|
||||
formData,
|
||||
success: resolve,
|
||||
fail: reject,
|
||||
...options
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 下载文件
|
||||
download(url, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.downloadFile({
|
||||
url: `${this.baseURL}${url}`,
|
||||
success: resolve,
|
||||
fail: reject,
|
||||
...options
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 创建请求实例
|
||||
const request = new Request()
|
||||
|
||||
// 添加请求拦截器 - Token处理
|
||||
request.addRequestInterceptor(async (config) => {
|
||||
const token = uni.getStorageSync('token')
|
||||
if (token) {
|
||||
config.header.Authorization = `Bearer ${token}`
|
||||
}
|
||||
return config
|
||||
})
|
||||
|
||||
// 添加响应拦截器 - 错误处理
|
||||
request.addResponseInterceptor(async (response) => {
|
||||
const { statusCode, data } = response
|
||||
|
||||
if (statusCode === 200) {
|
||||
if (data.code === 0) {
|
||||
return data.data
|
||||
} else {
|
||||
// 业务错误
|
||||
const error = new Error(data.message || '业务错误')
|
||||
error.code = data.code
|
||||
throw error
|
||||
}
|
||||
} else if (statusCode === 401) {
|
||||
// Token过期,尝试刷新
|
||||
return handleTokenExpired(response)
|
||||
} else {
|
||||
// 网络错误
|
||||
throw new Error(`网络错误: ${statusCode}`)
|
||||
}
|
||||
})
|
||||
|
||||
// Token过期处理
|
||||
async function handleTokenExpired(response) {
|
||||
if (isRefreshing) {
|
||||
// 如果正在刷新,将请求加入队列
|
||||
return new Promise((resolve) => {
|
||||
requestQueue.push(() => resolve(request.request(response.config)))
|
||||
})
|
||||
}
|
||||
|
||||
isRefreshing = true
|
||||
const refreshToken = uni.getStorageSync('refreshToken')
|
||||
|
||||
if (!refreshToken) {
|
||||
// 没有refreshToken,跳转到登录页
|
||||
uni.navigateTo({ url: '/pages/auth/login' })
|
||||
throw new Error('请重新登录')
|
||||
}
|
||||
|
||||
try {
|
||||
// 尝试刷新Token
|
||||
const result = await request.post(config.endpoints.USER.REFRESH_TOKEN, {
|
||||
refreshToken
|
||||
})
|
||||
|
||||
// 保存新Token
|
||||
uni.setStorageSync('token', result.token)
|
||||
uni.setStorageSync('refreshToken', result.refreshToken)
|
||||
|
||||
// 重试原始请求
|
||||
const retryResponse = await request.request(response.config)
|
||||
|
||||
// 处理队列中的请求
|
||||
processRequestQueue()
|
||||
|
||||
return retryResponse
|
||||
} catch (error) {
|
||||
// 刷新失败,清空Token并跳转登录
|
||||
uni.removeStorageSync('token')
|
||||
uni.removeStorageSync('refreshToken')
|
||||
uni.navigateTo({ url: '/pages/auth/login' })
|
||||
throw error
|
||||
} finally {
|
||||
isRefreshing = false
|
||||
}
|
||||
}
|
||||
|
||||
// 处理请求队列
|
||||
function processRequestQueue() {
|
||||
while (requestQueue.length > 0) {
|
||||
const retry = requestQueue.shift()
|
||||
retry()
|
||||
}
|
||||
}
|
||||
|
||||
export default request
|
||||
Reference in New Issue
Block a user