1. JavaScript API 设计核心原则在构建现代Web应用时API设计质量直接影响着开发体验和系统可维护性。经过多年实战我总结出JavaScript API设计的五大黄金法则1.1 一致性优先命名规范采用小驼峰命名法如getUserInfo参数顺序重要参数前置可选参数后置错误处理统一使用Error对象抛出异常1.2 最小接口原则典型反模式// 错误示范功能过度集中 class DataManager { fetch() {...} parse() {...} validate() {...} transform() {...} } // 正确做法职责分离 class DataFetcher {...} class DataParser {...} class DataValidator {...}1.3 可预测性设计输入输出类型严格一致避免隐式类型转换保持无副作用纯函数优先1.4 渐进式复杂度// 基础用法 api.get(/users) // 高级用法 api.get(/users, { cache: force-cache, timeout: 5000, retry: 3 })1.5 文档即代码推荐使用JSDoc标准/** * 获取用户详情 * param {string} id - 用户ID * param {object} [options] - 可选配置 * param {boolean} [options.cachetrue] - 是否启用缓存 * returns {PromiseUser} */ async function getUser(id, options) {...}2. RESTful API 最佳实践2.1 资源定位规范操作类型HTTP方法路径示例状态码创建POST/users201查询单个GET/users/{id}200查询列表GET/users200全量更新PUT/users/{id}200/204部分更新PATCH/users/{id}200/204删除DELETE/users/{id}2042.2 分页设计模板// 请求 GET /users?page2size20sortname,desc // 响应 { data: [...], pagination: { page: 2, size: 20, total: 153, hasNext: true } }2.3 缓存控制策略// 强制缓存 res.setHeader(Cache-Control, public, max-age3600) // 协商缓存 res.setHeader(ETag, fileHash) res.setHeader(Last-Modified, fileDate)3. 错误处理机制3.1 结构化错误响应{ error: { code: INVALID_TOKEN, message: Access token expired, details: { expiredAt: 2023-05-20T12:00:00Z }, stack: ... // 仅开发环境 } }3.2 常见错误分类类型HTTP状态码示例场景客户端错误400参数校验失败未授权401缺少认证信息禁止访问403权限不足资源不存在404接口路径错误冲突409重复创建资源服务器错误500数据库连接失败3.3 错误处理中间件app.use((err, req, res, next) { const status err.status || 500 res.status(status).json({ error: { code: err.code || INTERNAL_ERROR, message: err.message, ...(process.env.NODE_ENV development { stack: err.stack }) } }) })4. 性能优化技巧4.1 压缩传输方案// Express示例 const compression require(compression) app.use(compression({ threshold: 1024, // 只压缩大于1KB的响应 filter: (req) !req.headers[x-no-compression] }))4.2 批量操作支持// 批量查询接口设计 POST /users/_batch Body: { ids: [id1, id2, id3] } // 批量写入接口 POST /users/_bulk Body: [ {op: create, data: {...}}, {op: update, id: 123, data: {...}} ]4.3 延迟加载模式// 按需加载字段 GET /users/123?fieldsname,avatar // 关联资源延迟加载 GET /users/123/posts?limit55. 安全防护措施5.1 输入验证模板const schema Joi.object({ username: Joi.string().alphanum().min(3).max(30).required(), email: Joi.string().email(), birthYear: Joi.number().integer().min(1900).max(2023) }) const { error, value } schema.validate(req.body) if (error) throw new BadRequestError(error.details)5.2 速率限制配置const rateLimit require(express-rate-limit) const apiLimiter rateLimit({ windowMs: 15 * 60 * 1000, // 15分钟 max: 100, // 每个IP限制100次请求 message: { error: { code: TOO_MANY_REQUESTS, message: 请求过于频繁 } } }) app.use(/api/, apiLimiter)5.3 CORS安全设置app.use(cors({ origin: [https://example.com], methods: [GET, POST, PUT], allowedHeaders: [Content-Type, Authorization], maxAge: 86400, credentials: true }))6. 文档与测试6.1 OpenAPI规范示例paths: /users/{id}: get: tags: [Users] summary: 获取用户详情 parameters: - $ref: #/components/parameters/userId responses: 200: description: 用户对象 content: application/json: schema: $ref: #/components/schemas/User components: schemas: User: type: object properties: id: {type: string} name: {type: string} parameters: userId: name: id in: path required: true schema: {type: string}6.2 自动化测试策略describe(User API, () { let testUser beforeAll(async () { testUser await User.create({...}) }) it(GET /users/:id 应返回用户详情, async () { const res await request(app) .get(/users/${testUser.id}) .expect(200) expect(res.body).toMatchObject({ id: testUser.id, name: testUser.name }) }) it(POST /users 应创建新用户, () { return request(app) .post(/users) .send({name: New User}) .expect(201) }) })7. 版本管理方案7.1 多版本共存策略/api/v1/users /api/v2/users7.2 版本迁移检查清单维护版本变更日志提供兼容层中间件设置旧版API过期时间监控旧版API使用情况// 版本兼容处理 app.use(/api/:version, (req, res, next) { if (req.params.version v1) { // 转换v1参数到v2格式 req.query convertV1Query(req.query) } next() })8. 实时API设计8.1 WebSocket事件规范// 连接建立 ws.send(JSON.stringify({ event: AUTH, data: {token: xxx} })) // 事件推送 { event: MESSAGE_CREATED, data: {...}, timestamp: 1685000000 }8.2 心跳检测机制// 服务端 setInterval(() { clients.forEach(ws { if (Date.now() - ws.lastActive 30000) { ws.terminate() } }) }, 5000) // 客户端 const heartbeat () { ws.lastPing Date.now() ws.ping() } ws.on(pong, heartbeat) setInterval(heartbeat, 10000)9. 调试与监控9.1 请求日志格式{ timestamp: 2023-05-25T08:30:45Z, method: GET, path: /users/123, status: 200, duration: 45, ip: 192.168.1.100, userAgent: Chrome/113.0, requestId: req_abc123 }9.2 性能监控指标# HELP api_request_duration API请求耗时 # TYPE api_request_duration histogram api_request_duration_bucket{methodGET,path/users,le100} 123 api_request_duration_bucket{methodGET,path/users,le500} 456 # HELP api_error_count API错误统计 # TYPE api_error_count counter api_error_count{code404} 5 api_error_count{code500} 210. 前沿技术整合10.1 GraphQL混合方案// RESTful路由 app.get(/api/users/:id, getUser) // GraphQL端点 app.use(/graphql, graphqlHTTP({ schema, graphiql: true })) // 类型定义示例 type User { id: ID! name: String! posts(limit: Int 5): [Post!]! }10.2 Serverless适配// AWS Lambda处理程序 exports.handler async (event) { const { path, httpMethod, queryStringParameters } event if (path /users httpMethod GET) { return { statusCode: 200, body: JSON.stringify(await listUsers(queryStringParameters)) } } }在真实项目中我曾遇到一个典型的API设计问题用户反馈分页接口在数据量达到百万级时性能急剧下降。通过实现游标分页方案我们将响应时间从原来的1200ms降低到稳定200ms以内。关键改进点是// 传统分页 GET /items?page3size20 // 游标分页 GET /items?cursorabc123limit20 // 响应 { data: [...], nextCursor: def456, hasMore: true }这种设计不仅提升了性能还解决了传统分页在数据变更时出现的跳页问题。建议在设计初期就考虑数据规模的增长趋势选择合适的分页策略。