/** * API 请求管理器 * 统一处理网络请求、错误处理、请求拦截 */ const { logger } = require('./logger.js') const { cacheManager } = require('./performance.js') class Request { constructor(config = {}) { this.baseURL = config.baseURL || '' this.timeout = config.timeout || 10000 this.header = config.header || { 'Content-Type': 'application/json' } this.interceptors = { request: [], response: [] } } /** * 请求拦截器 */ useRequestInterceptor(handler) { this.interceptors.request.push(handler) } /** * 响应拦截器 */ useResponseInterceptor(handler) { this.interceptors.response.push(handler) } /** * 发送请求 */ async request(options) { let config = { url: this.baseURL + options.url, method: options.method || 'GET', data: options.data || {}, header: { ...this.header, ...options.header }, timeout: options.timeout || this.timeout } // 执行请求拦截器 for (const interceptor of this.interceptors.request) { config = await interceptor(config) } // 检查缓存 if (config.method === 'GET' && options.cache) { const cacheKey = this._getCacheKey(config) const cached = cacheManager.get(cacheKey) if (cached) { logger.debug('使用缓存数据', { url: config.url }) return cached } } const startTime = Date.now() try { const response = await this._wxRequest(config) // 执行响应拦截器 let result = response for (const interceptor of this.interceptors.response) { result = await interceptor(result) } // 缓存GET请求结果 if (config.method === 'GET' && options.cache) { const cacheKey = this._getCacheKey(config) cacheManager.set(cacheKey, result, options.cacheTTL) } // 记录性能 const duration = Date.now() - startTime logger.debug('请求成功', { url: config.url, duration: `${duration}ms` }) return result } catch (error) { const duration = Date.now() - startTime logger.error('请求失败', { url: config.url, duration: `${duration}ms`, error }) throw this._handleError(error) } } /** * 微信请求封装 */ _wxRequest(config) { return new Promise((resolve, reject) => { wx.request({ ...config, success: (res) => { if (res.statusCode >= 200 && res.statusCode < 300) { resolve(res.data) } else { reject({ statusCode: res.statusCode, message: res.data.message || '请求失败', data: res.data }) } }, fail: (err) => { reject({ statusCode: 0, message: err.errMsg || '网络错误', error: err }) } }) }) } /** * 错误处理 */ _handleError(error) { const errorMap = { 0: '网络连接失败', 400: '请求参数错误', 401: '未授权,请登录', 403: '拒绝访问', 404: '请求的资源不存在', 500: '服务器错误', 502: '网关错误', 503: '服务不可用', 504: '网关超时' } return { code: error.statusCode, message: errorMap[error.statusCode] || error.message || '未知错误', data: error.data } } /** * 获取缓存键 */ _getCacheKey(config) { return `${config.method}:${config.url}:${JSON.stringify(config.data)}` } /** * GET 请求 */ get(url, params = {}, options = {}) { return this.request({ url, method: 'GET', data: params, ...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) => { const uploadTask = wx.uploadFile({ url: this.baseURL + url, filePath, name: options.name || 'file', formData, header: { ...this.header, ...options.header }, success: (res) => { if (res.statusCode >= 200 && res.statusCode < 300) { resolve(JSON.parse(res.data)) } else { reject({ statusCode: res.statusCode, message: '上传失败' }) } }, fail: reject }) // 进度回调 if (options.onProgress) { uploadTask.onProgressUpdate(options.onProgress) } }) } /** * 下载文件 */ download(url, options = {}) { return new Promise((resolve, reject) => { const downloadTask = wx.downloadFile({ url: this.baseURL + url, header: { ...this.header, ...options.header }, success: (res) => { if (res.statusCode >= 200 && res.statusCode < 300) { resolve(res.tempFilePath) } else { reject({ statusCode: res.statusCode, message: '下载失败' }) } }, fail: reject }) // 进度回调 if (options.onProgress) { downloadTask.onProgressUpdate(options.onProgress) } }) } } // 创建全局实例 const request = new Request({ baseURL: 'https://api.example.com', // TODO: 替换为实际API地址 timeout: 10000 }) // 添加请求拦截器 request.useRequestInterceptor(async (config) => { // 添加 token const token = wx.getStorageSync('token') if (token) { config.header['Authorization'] = `Bearer ${token}` } // 显示加载提示 if (config.loading !== false) { wx.showLoading({ title: '加载中...', mask: true }) } return config }) // 添加响应拦截器 request.useResponseInterceptor(async (response) => { // 隐藏加载提示 wx.hideLoading() // 统一处理业务错误码 if (response.code !== 0 && response.code !== 200) { wx.showToast({ title: response.message || '操作失败', icon: 'none' }) throw response } return response.data || response }) module.exports = { Request, request }