微信小程序 wx.request() 的封装
基于微信小程序的wx.request()方法封装
下面是一个封装方案,满足您提出的所有要求:
class HttpService {constructor() {this.baseUrl = ''; // 基础URLthis.pendingRequests = new Map(); // 请求缓存池this.interceptors = {request: [],response: []};}// 设置基础URLsetBaseUrl(url) {this.baseUrl = url;}// 添加拦截器useInterceptor(type, handler) {if (this.interceptors[type]) {this.interceptors[type].push(handler);}}// 核心请求方法async request(config) {const { url, method = 'GET', data = {}, header = {}, showLoading = false } = config;// 生成请求唯一标识const requestKey = `${method}_${url}_${JSON.stringify(data)}`;// 检查重复请求if (this.pendingRequests.has(requestKey)) {return this.pendingRequests.get(requestKey);}// 请求前拦截处理let finalConfig = { url, method, data, header, showLoading };for (const interceptor of this.interceptors.request) {finalConfig = await interceptor(finalConfig) || finalConfig;}// 创建请求Promiseconst requestPromise = new Promise((resolve, reject) => {// 显示加载状态if (finalConfig.showLoading) {wx.showLoading({ title: '加载中', mask: true });}wx.request({url: this.baseUrl + finalConfig.url,method: finalConfig.method,data: finalConfig.data,header: finalConfig.header,success: async (res) => {// 响应后拦截处理let processedRes = res;for (const interceptor of this.interceptors.response) {processedRes = await interceptor(processedRes) || processedRes;}resolve(processedRes);},fail: (err) => {// 错误处理拦截let processedErr = err;for (const interceptor of this.interceptors.response) {processedErr = interceptor(processedErr) || processedErr;}reject(processedErr);},complete: () => {// 隐藏加载状态if (finalConfig.showLoading) {wx.hideLoading();}// 从缓存池移除this.pendingRequests.delete(requestKey);}});});// 缓存当前请求this.pendingRequests.set(requestKey, requestPromise);return requestPromise;}// 并发请求处理all(requests) {return Promise.all(requests);}// 快捷方法:GETget(url, params = {}, config = {}) {return this.request({...config,url,method: 'GET',data: params});}// 快捷方法:POSTpost(url, data = {}, config = {}) {return this.request({...config,url,method: 'POST',data});}// 快捷方法:PUTput(url, data = {}, config = {}) {return this.request({...config,url,method: 'PUT',data});}// 快捷方法:DELETEdelete(url, params = {}, config = {}) {return this.request({...config,url,method: 'DELETE',data: params});}
}// 创建实例
const http = new HttpService();// 设置基础URL(示例)
http.setBaseUrl('https://api.example.com');// 添加请求拦截器(示例:添加token)
http.useInterceptor('request', (config) => {const token = wx.getStorageSync('token');if (token) {config.header = {...config.header,Authorization: `Bearer ${token}`};}return config;
});// 添加响应拦截器(示例:错误处理)
http.useInterceptor('response', (response) => {if (response.statusCode !== 200) {wx.showToast({title: `请求错误: ${response.data.message || '未知错误'}`,icon: 'none'});throw new Error('请求失败');}return response.data;
});
功能说明
加载状态控制
- 通过
showLoading
参数控制是否显示加载动画 - 默认不显示,需要时手动开启
- 使用微信原生
showLoading/hideLoading
方法
- 通过
拦截器系统
- 请求拦截器:在请求发送前修改配置
- 响应拦截器:处理响应数据和错误
- 支持添加多个拦截器,按添加顺序执行
并发请求处理
all()
方法处理多个并发请求- 内部使用
Promise.all
实现 - 示例用法:
const [userData, productList] = await http.all([http.get('/user'),http.get('/products') ]);
重复请求过滤
- 使用请求方法+URL+参数的哈希值作为唯一标识
- 相同请求返回缓存中的Promise对象
- 避免网络资源浪费
快捷方法
- 内置GET/POST/PUT/DELETE快捷方法
- 简化常用请求调用
- 示例:
// GET请求 const data = await http.get('/api/data', { page: 1 });// POST请求 await http.post('/api/submit', { name: 'John' }, { showLoading: true });
使用示例
// 获取用户信息
async function fetchUser() {try {const user = await http.get('/user/profile', null, { showLoading: true });console.log('用户数据:', user);} catch (error) {console.error('获取用户信息失败', error);}
}// 提交表单数据
async function submitForm(data) {try {const result = await http.post('/form/submit', data, {showLoading: true,header: { 'Content-Type': 'application/json' }});wx.showToast({ title: '提交成功' });} catch (error) {// 错误已在拦截器处理}
}// 并发请求示例
async function fetchAllData() {try {const [orders, messages] = await http.all([http.get('/user/orders'),http.get('/user/messages')]);console.log('订单数据:', orders);console.log('消息数据:', messages);} catch (error) {console.error('数据获取失败', error);}
}
这个封装方案具有以下优势:
- 完整的拦截器系统支持预处理和后处理
- 智能的请求缓存机制避免重复请求
- 简洁的API设计降低使用复杂度
- 完善的错误处理流程
- 灵活的加载状态控制
- TypeScript友好,可轻松添加类型定义