uniapp网络请求功能比较基础, 缺乏请求拦截,响应拦截,所以我封装了一个丐版Axios, 废话不多说, 直接上代码。
// http.js
export default class HttpRequest {
constructor(baseURL) {
this.baseURL = baseURL;
this.interceptors = {
request: [],
response: []
};
}
// 添加请求拦截器
interceptorRequest(fulfil, reject) {
this.interceptors.request.push({ fulfil, reject });
}
// 添加响应拦截器
interceptorResponse(fulfil, reject) {
this.interceptors.response.push({ fulfil, reject });
}
// 请求方法
/**
* 请求方法
* @param {{url:string, method: 'GET'|'POST'|'PUT'|'DELETE', data: any, header:any}} options
* @returns {Promise<unknown>}
*/
async request(options) {
if(!options.url) {
options.url = ''
}
// 合并基础配置
const finalConfig = {
...options,
url: this.baseURL + options.url,
method: options.method || 'GET',
header: options.header || { 'content-type': 'application/json' },
};
// 应用请求拦截器
let requestInterceptors = this.interceptors.request;
for (let interceptor of requestInterceptors) {
await interceptor.fulfil(finalConfig);
}
// 发送请求
return new Promise((resolve, reject) => {
uni.request({
...finalConfig,
success: (response) => {
// 应用响应拦截器
let responseInterceptors = this.interceptors.response;
let res = response.data;
if (response.statusCode < 400) {
for (let interceptor of responseInterceptors) {
// 响应拦截器存入请求参数
res = interceptor.fulfil(res, options);
}
resolve(res);
} else {
reject(res);
}
},
fail: (error) => {
// 应用响应拦截器
let responseInterceptors = this.interceptors.response;
let err = error;
for (let interceptor of responseInterceptors) {
err = interceptor.reject(err);
}
reject(err);
}
});
});
}
// 单例模式获取实例
static getInstance(baseURL) {
if (this.instance) {
return this.instance;
} else {
this.instance = new HttpRequest(baseURL);
return this.instance;
}
}
}
接下来对http.js进行简单封装, 方便使用。
// request.js
import HttpRequest from './http.js';
export const request = (options = {}) => {
const http = HttpRequest.getInstance(import.meta.env.VITE_APP_BASE_API);
http.interceptorRequest((config) => {
// 添加拦截代码
return config;
}, (error) => {
console.error('Request Error:', error);
return error;
});
// 响应拦截器传入请求参数
http.interceptorResponse((response, config) => {
// 对响应数据做点什么
// 示例业务代码
if (response.code === -998) {
// 登录过期
return new Promise((resolve, reject) => {
- addRequest(() => resolve(http.request(options)))
+ addRequest(() => resolve(http.request(config)))
refreshToken()
})
}
if (!response.ok) {
uni.showToast({
title: response?.msg || '请求失败',
icon: 'none',
})
return response
}
return response;
}, (error) => {
// 对响应错误做点什么
uni.showToast({
title: error?.msg || error?.message || '请求失败',
icon: 'none',
})
return Promise.reject(error);
});
return http.request(options)
}
长短token无感刷新代码
let subscribes = []
let flag = false // 设置开关,保证一次只能请求一次短token,防止多此操作,多次请求
/*把过期请求添加在数组中*/
export const addRequest = (request) => {
subscribes.push(request)
}
/*调用过期请求*/
export const retryRequest = () => {
console.log('重新请求上次中断的数据');
console.log(subscribes);
subscribes.forEach(request => request())
subscribes = []
}
调用refreshToken方法刷新token后, 调用retryRequest方法重新请求上次中断的数据
之前的代码响应拦截保存请求有一处,现已更正