UNPKG

mp-mini-axios

Version:

MiniAxios 是一个轻量级 HTTP 客户端库,专为【微信小程序】设计,提供类似 Axios 的 API 接口。它支持请求/响应拦截器、取消请求、自动重试、文件上传/下载等功能。构建后大小11KB,能有效节省小程序包大小。

492 lines (408 loc) 12.8 kB
# MiniAxios 使用文档 MiniAxios 是一个轻量级 HTTP 客户端库,专为【微信小程序】设计,提供类似 Axios 的 API 接口。它支持请求/响应拦截器、取消请求、自动重试、文件上传/下载等功能。构建后大小11KB,能有效节省小程序包大小。 ## 关于模块名称与类名 最开始,打算把模块叫做mini-axios,发布...重名。改名为nano-axios,还得意洋洋写了句,nano < mirco < mini,发布...又重!又改名为mp-axios,又说和mp_axios太像,最终改为mp-mini-axios。由于开发的时候使用了MiniAxios作为类名,这里就不改了。 ## 安装与引入 ### 1. 使用模块 ``` // 1. 安装模块 npm i mp-mini-axios; // 2. 构建npm 微信开发者工具 > 工具 > 构建 npm // 3. 项目引入 import axios, { MiniAxios, CancelToken, AbortController } from 'mp-mini-axios'; ``` ### 2. 复制源码到项目 将模块中的源码复制到小程序项目中: - `src/index.js` - 导出文件 - `src/MiniAxios.js` - 核心库 - `src/CancelToken.js` - 取消令牌实现 - `src/AbortController.js` - 中止控制器实现 ```javascript import axios, { MiniAxios, CancelToken, AbortController } from './libs/miniAxios/index.js'; import axios, { MiniAxios } from './libs/miniAxios/MiniAxios.js'; import { CancelToken } from './libs/miniAxios/CancelToken.js'; import { AbortController } from './libs/miniAxios/AbortController.js'; ``` ## 创建实例 ### 1. 使用默认实例 ```javascript // 使用默认配置 axios.get('/api/data') .then(response => console.log(response.data)) .catch(error => console.error(error)); ``` ### 2. 使用工厂函数创建实例 ```javascript // 使用 create 方法创建实例 const api = axios.create({ baseURL: 'https://api.example.com', timeout: 10000, headers: { 'X-Custom-Header': 'custom-value' } }); // 使用自定义实例 api.post('/users', { name: 'John' }) .then(response => console.log(response.data)) .catch(error => console.error(error)); ``` ### 3. 使用类创建实例 ```javascript // 创建自定义实例 const api = new MiniAxios({ baseURL: 'https://api.example.com', timeout: 10000, headers: { 'X-Custom-Header': 'custom-value' } }); // 使用自定义实例 api.post('/users', { name: 'John' }) .then(response => console.log(response.data)) .catch(error => console.error(error)); ``` ## 配置项 MiniAxios 支持以下配置选项: | 配置项 | 类型 | 默认值 | 说明 | |--------|------|---------|------| | `baseURL` | string | `''` | 基础 URL | | `timeout` | number | `60000` | 请求超时时间(ms) | | `headers`/`header` | object | `{}` | 请求头 | | `retry` | boolean/number | `false` | 是否重试及重试次数 | | `retryDelay` | number | `1000` | 重试延迟时间(ms) | | `method` | string | `'get'` | 请求方法 | | `params`/`query` | object | `{}` | URL 查询参数 | | `data`/`body` | object | `{}` | 请求体数据 | | `filePath` | string | `''` | 文件路径(上传/下载) | | `name`/`fileName` | string | `'file'` | 文件字段名(上传) | | `cancelToken` | CancelToken | `null` | 取消令牌 | | `signal` | AbortSignal | `null` | 中止信号 | | `onRetry` | function | `null` | 重试回调 | | `onProgressUpdate` | function | `null` | 进度更新回调 | | `onHeadersReceived` | function | `null` | 头部接收回调 | | `enableCache` | boolean | `false` | 是否启用缓存 | | `enableHttp2` | boolean | `false` | 是否启用 HTTP/2 | | `enableQuic` | boolean | `false` | 是否启用 QUIC | ## 请求方法 ### 1. 基本请求方法 ```javascript // GET 请求 axios.get('/api/data', { params: { id: 123 } }).then(response => console.log(response.data)); // POST 请求 axios.post('/api/users', { name: 'John', age: 30 }).then(response => console.log('创建成功')); // PUT 请求 axios.put('/api/users/123', { name: 'John Updated' }).then(response => console.log('更新成功')); // DELETE 请求 axios.delete('/api/users/123') .then(response => console.log('删除成功')); // HEAD 请求 axios.head('/api/data') .then(response => console.log(response.headers)); // OPTIONS 请求 axios.options('/api/data') .then(response => console.log(response.headers)); ``` ### 2. 通用请求方法 ```javascript axios.request({ url: '/api/data', method: 'post', data: { key: 'value' }, headers: { 'Content-Type': 'application/json' } }).then(response => console.log(response.data)); ``` ## 文件上传与下载 ### 1. 文件上传 ```javascript // uploadFile(config) // uploadFile(url, config) // uploadFile(url, formData, config) axios.uploadFile('/upload', { description: '用户头像' otherFormData: 'xxx', }, { filePath: '/path/to/avatar.jpg', name: 'avatar', // 可选,默认 'file' onProgressUpdate: progress => { console.log(`上传进度: ${progress.progress}%`); } }).then(response => { console.log('上传成功', response.data); }).catch(error => { console.error('上传失败', error); }); ``` ### 2. 文件下载 ```javascript // downloadFile(config) // downloadFile(url, config) axios.downloadFile('/file.pdf', { filePath: '/path/to/save.pdf', onProgressUpdate: progress => { console.log(`下载进度: ${progress.progress}%`); } }).then(response => { console.log('下载成功', response.data.tempFilePath); }).catch(error => { console.error('下载失败', error); }); ``` ## 拦截器 ### 1. 请求拦截器 ```javascript // 添加请求拦截器 axios.interceptors.request.use(config => { // 添加认证令牌 config.headers.Authorization = 'Bearer token'; // 记录请求日志 console.log('发送请求:', config.url); return config; }, error => { // 处理请求错误 return Promise.reject(error); }); ``` ### 2. 响应拦截器 ```javascript // 添加响应拦截器 axios.interceptors.response.use(response => { // 处理响应数据 console.log('收到响应:', response.status); // 只返回数据部分 return response.data; }, error => { // 处理响应错误 if (error.response && error.response.status === 401) { // 处理未授权错误 console.log('未授权,跳转到登录页'); } return Promise.reject(error); }); ``` ### 3. 移除拦截器 ```javascript // 添加拦截器 const interceptorId = axios.interceptors.request.use(/* ... */); // 移除拦截器 axios.interceptors.request.eject(interceptorId); ``` ## 取消请求 ### 1. 使用 CancelToken ```javascript // 创建取消令牌 const source = CancelToken.source(); // 发起请求 axios.get('/api/data', { cancelToken: source.token }).catch(error => { if (MiniAxios.isCancel(error)) { console.log('请求已取消:', error.message); } }); // 取消请求 source.cancel('用户取消了请求'); ``` ### 2. 使用 AbortController ```javascript // 创建中止控制器 const controller = new AbortController(); // 发起请求 axios.get('/api/data', { signal: controller.signal }).catch(error => { if (error.code === 'ECONNABORTED') { console.log('请求已中止:', error.message); } }); // 中止请求 controller.abort('用户中止了请求'); ``` ## 错误处理 ### 1. 错误对象结构 错误对象包含以下属性: ```javascript { message: '错误消息', code: '错误代码', config: '请求配置', request: '请求对象', response: '响应对象(如果有)', status: 'HTTP状态码', retryCount: '重试次数(如果有)' } ``` ### 2. 常见错误代码 | 错误代码 | 说明 | |----------|------| | `ETIMEDOUT` | 请求超时 | | `ECONNABORTED` | 请求被中止 | | `ERR_BAD_REQUEST` | 客户端错误(4xx) | | `ERR_BAD_RESPONSE` | 服务器错误(5xx) | | `WX_API_ERROR` | 微信API错误 | ### 3. 错误处理示例 ```javascript axios.get('/api/data') .then(response => console.log(response.data)) .catch(error => { if (error.code === 'ETIMEDOUT') { console.log('请求超时'); } else if (error.code === 'ECONNABORTED') { console.log('请求被中止'); } else if (error.response) { console.log(`服务器错误: ${error.response.status}`); } else { console.log('未知错误', error); } }); ``` ## 重试机制 ### 1. 基本重试配置 ```javascript axios.get('/api/data', { retry: 3, // 重试3retryDelay: 2000, // 每次重试间隔2onRetry: (retryInfo) => { console.log(`重试 #${retryInfo.retryCount}, 错误: ${retryInfo.error.message}`); } }).then(response => { console.log('最终响应:', response.data); }).catch(error => { console.log('最终失败:', error.message); }); ``` ### 2. 指数退避策略 MiniAxios 默认使用指数退避策略: - 第一次重试延迟: `retryDelay` - 第二次重试延迟: `retryDelay * 2` - 第三次重试延迟: `retryDelay * 4` - 以此类推 ## 完整配置示例 ```javascript // 创建自定义实例 const api = new MiniAxios({ baseURL: 'https://api.example.com', timeout: 15000, headers: { 'X-Client': 'MiniApp' }, retry: 2, retryDelay: 1000 }); // 添加拦截器 api.interceptors.request.use(config => { config.headers.Authorization = 'Bearer token'; return config; }); api.interceptors.response.use(response => { return response.data; }, error => { return Promise.reject(error); }); // 发起请求 api.post('/users', { name: 'John', email: 'john@example.com' }, { onProgressUpdate: progress => { console.log(`请求进度: ${progress.progress}%`); } }).then(data => { console.log('用户创建成功', data); }).catch(error => { console.error('创建用户失败', error); }); ``` ## 注意事项 1. **小程序限制**: - 文件上传需使用 `wx.uploadFile` - 文件下载需使用 `wx.downloadFile` - 部分 API 在小程序中有特殊限制 2. **取消请求**: - 小程序中取消请求使用 `requestTask.abort()` - 取消后请求会立即失败 3. **错误处理**: - 使用自定义错误类 - 错误对象中包含微信原生错误信息 4. **重试机制**: - 默认只对非取消错误重试 - 可自定义重试条件和重试策略 5. **性能优化**: - 避免在拦截器中执行耗时操作 - 合理设置超时时间 - 按需使用重试机制 ## 最佳实践 1. **封装 API 模块**: ```javascript // api.js import axios from 'mp-mini-axios'; const api = axios.create({ baseURL: 'https://api.example.com' }); export default { getUsers: () => api.get('/users'), createUser: (userData) => api.post('/users', userData), uploadAvatar: (filePath, data) => api.uploadFile('/upload/avatar', data, { filePath }) }; ``` 2. **统一错误处理**: ```javascript // 全局错误处理 api.interceptors.response.use(null, error => { if (error.response && error.response.status === 401) { // 跳转到登录页 wx.redirectTo({ url: '/pages/login' }); } return Promise.reject(error); }); ``` 3. **请求取消封装**: ```javascript // 封装可取消请求 function makeCancelableRequest(request) { const source = CancelToken.source(); const requestPromise = request(source.token); return { promise: requestPromise, cancel: (message) => source.cancel(message || '请求已取消') }; } // 使用 const { promise, cancel } = makeCancelableRequest( token => api.get('/data', { cancelToken: token }) ); // 取消请求 cancel(); ``` 4. **上传/下载进度显示**: ```javascript // 上传文件显示进度 api.uploadFile('/upload', {}, { filePath: '/path/to/file', onProgressUpdate: progress => { wx.showToast({ title: `上传中 ${progress.progress}%`, icon: 'none' }); } }); ``` ## 总结 MiniAxios 为微信小程序提供了强大的 HTTP 客户端功能,主要特点包括: 1. **类 Axios API**:熟悉的 API 设计,降低学习成本 2. **请求/响应拦截器**:灵活处理请求和响应 3. **取消请求**:支持 CancelToken 和 AbortController 两种方式 4. **自动重试**:内置指数退避重试策略 5. **文件支持**:简化文件上传/下载操作 6. **错误处理**:统一错误处理机制 7. **配置灵活**:支持全局配置和请求级配置 通过合理使用 MiniAxios,可以大大简化小程序中的网络请求处理,提高开发效率和代码质量。