相信大家总是多多少少会有这样的感觉,有时在写项目接口的时候,总是不知道从何入手,这个时候如果有一些模版或者最佳实践可供参考,下面就整理了一些相关的最佳实践,涵盖设计、实现、维护全流程
一、接口设计规范
-
遵循 RESTful 风格 • HTTP 方法语义化:GET(查询)、POST(创建)、PUT(更新)、DELETE(删除)
• 状态码规范:200(成功)、400(客户端错误)、401(未授权)、404(资源不存在)、500(服务端错误)
• 统一响应格式:
json{ "code": 200, "data": { ... }, "message": "success" }
-
接口版本管理 • URL 路径版本:
/api/v1/users
• 请求头版本:
Accept: application/vnd.myapi.v1+json
二、请求处理最佳实践
-
封装请求库
javascript// 封装 Axios 实例 const apiClient = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL, timeout: 10000, headers: { 'Content-Type': 'application/json' } }); // 请求拦截器(添加 Token) apiClient.interceptors.request.use(config => { const token = localStorage.getItem('token'); if (token) config.headers.Authorization = `Bearer ${token}`; return config; }); // 响应拦截器(统一错误处理) apiClient.interceptors.response.use( response => response.data, error => { if (error.response?.status === 401) { handleLogout(); // Token 过期跳转登录 } return Promise.reject(error); } );
-
参数处理 • 查询参数序列化:
javascriptfunction serializeParams(params) { return new URLSearchParams(params).toString(); } // 使用:apiClient.get(`/users?${serializeParams({ page: 1, size: 10 })}`)
• 请求体处理:自动序列化 JSON 对象。
三、错误处理核心逻辑
-
全局错误捕获
javascript// 统一处理 API 错误 async function fetchData() { try { const res = await apiClient.get('/users'); return res.data; } catch (error) { if (error.response) { // 服务端返回的错误(如 400/500) showErrorToast(error.response.data.message); } else if (error.request) { // 网络错误 showErrorToast('网络连接失败'); } throw error; // 允许上层继续处理 } }
-
重试机制
javascriptasync function fetchWithRetry(url, retries = 3) { try { return await apiClient.get(url); } catch (error) { if (retries > 0) { await new Promise(resolve => setTimeout(resolve, 1000)); return fetchWithRetry(url, retries - 1); } throw error; } }
四、性能优化策略
-
请求缓存
javascriptconst cache = new Map(); async function fetchCached(url) { if (cache.has(url)) return cache.get(url); const data = await apiClient.get(url); cache.set(url, data); return data; }
-
防抖与节流
javascript// 搜索框防抖 const debouncedSearch = debounce(async (keyword) => { const res = await apiClient.get(`/search?q=${keyword}`); updateResults(res.data); }, 300);
-
并发请求合并
javascript// 使用 Promise.all 并行请求 const [user, posts] = await Promise.all([ apiClient.get('/user/1'), apiClient.get('/posts?userId=1') ]);
五、环境与配置管理
-
多环境配置
javascript// .env.development VITE_API_BASE_URL=http://localhost:3000/api // .env.production VITE_API_BASE_URL=https://api.example.com
-
接口Mock(开发阶段)
javascript// 本地 Mock 示例(使用 Mock.js) Mock.mock('/api/user', 'get', { 'id|1-100': 100, 'name': '@cname' });
六、安全实践
-
防御 XSS/CSRF • 对用户输入做转义:
DOMPurify.sanitize(rawHtml)
• 启用 CSRF Token:通过 Cookie + Header 双重验证
-
敏感信息处理 • 禁止明文存储 Token:使用
httpOnly
Cookie• 避免 URL 参数暴露敏感数据:优先用 POST Body
七、测试策略
-
单元测试
javascript// 测试接口请求逻辑 test('fetchUser 成功', async () => { mockApiResponse({ id: 1, name: 'Alice' }); const user = await fetchUser(1); expect(user.name).toBe('Alice'); });
-
E2E 测试
javascript// 使用 Cypress 测试完整流程 cy.intercept('/api/login', { fixture: 'login-success.json' }); cy.visit('/login'); cy.get('input#email').type('[email protected]'); cy.get('button[type="submit"]').click(); cy.url().should('include', '/dashboard');
八、文档与协作
-
自动生成文档 • 使用 Swagger/OpenAPI:通过注释生成接口文档
javascript/** * @swagger * /api/users: * get: * summary: 获取用户列表 * responses: * 200: * description: 用户列表数据 */
-
接口变更通知 • 通过邮件/Slack 通知团队
• 维护版本变更日志(CHANGELOG.md)
九、工具链推荐
类型 | 工具推荐 |
---|---|
请求库 | Axios、Fetch API |
数据缓存 | SWR、React Query |
类型定义 | TypeScript、Zod |
Mock 工具 | JSON Server、Mock.js |
监控 | Sentry、LogRocket |
十、TypeScript 增强
typescript
// 定义接口类型
interface User {
id: number;
name: string;
}
// 封装带类型的请求函数
async function getUser(id: number): Promise<User> {
const res = await apiClient.get(`/users/${id}`);
return res.data;
}
关键总结
- 标准化:统一接口格式、错误处理、响应结构
- 健壮性:拦截器、重试机制、超时控制
- 可维护性:模块化拆分、类型定义、文档驱动
- 性能:缓存策略、并发控制、懒加载
- 协作:Mock 数据、环境隔离、接口版本管理
根据项目规模选择合适的方案,小型项目可直接封装 Axios,中大型项目建议引入 Redux/SWR/React Query 等状态管理库。