前端API设计最佳实践:让你的API更优雅

前端API设计最佳实践:让你的API更优雅

毒舌时刻

API设计?听起来就像是后端工程师的事情,关前端什么事?你以为前端只需要调用API就可以了?别天真了!如果API设计得不好,前端开发会变得非常痛苦。

你以为随便设计个API就能用?别做梦了!我见过太多糟糕的API设计,比如返回的数据结构不一致,错误处理不规范,文档不完整,这些都会让前端开发者崩溃。

为什么你需要这个

  1. 提高开发效率:良好的API设计可以减少前端开发的工作量,提高开发效率。
  2. 减少错误:规范的API设计可以减少前端开发中的错误,提高代码的可靠性。
  3. 改善用户体验:合理的API设计可以提高应用的响应速度,改善用户体验。
  4. 便于维护:良好的API设计可以使代码更易于维护,减少后期的维护成本。
  5. 促进团队协作:规范的API设计可以促进前后端团队的协作,减少沟通成本。

反面教材

// 这是一个典型的糟糕API设计 // 1. 不一致的命名规范 // 获取用户列表 fetch('/api/getUsers') .then(response => response.json()) .then(data => console.log(data)); // 获取单个用户 fetch('/api/user/1') .then(response => response.json()) .then(data => console.log(data)); // 2. 不一致的返回格式 // 成功返回 // { "status": "success", "data": { "id": 1, "name": "John" } } // 失败返回 // { "error": "User not found" } // 3. 不规范的错误处理 fetch('/api/users') .then(response => { if (response.status === 200) { return response.json(); } else if (response.status === 404) { throw new Error('Not found'); } else if (response.status === 500) { throw new Error('Server error'); } else { throw new Error('Unknown error'); } }) .then(data => console.log(data)) .catch(error => console.error(error)); // 4. 缺少分页和过滤 fetch('/api/users') .then(response => response.json()) .then(data => { // 当用户数量很多时,会返回大量数据,影响性能 console.log(data); }); 

问题

  • 命名规范不一致,有的使用驼峰命名,有的使用下划线命名
  • 返回格式不一致,成功和失败的返回格式不同
  • 错误处理不规范,需要手动处理不同的状态码
  • 缺少分页和过滤功能,返回大量数据时影响性能
  • 缺少版本控制,后续API变更时会影响现有代码

正确的做法

RESTful API设计

// 1. 一致的命名规范 // 获取用户列表 fetch('/api/v1/users') .then(response => response.json()) .then(data => console.log(data)); // 获取单个用户 fetch('/api/v1/users/1') .then(response => response.json()) .then(data => console.log(data)); // 创建用户 fetch('/api/v1/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'John', email: '[email protected]' }) }) .then(response => response.json()) .then(data => console.log(data)); // 更新用户 fetch('/api/v1/users/1', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'John Doe', email: '[email protected]' }) }) .then(response => response.json()) .then(data => console.log(data)); // 删除用户 fetch('/api/v1/users/1', { method: 'DELETE' }) .then(response => response.json()) .then(data => console.log(data)); 

一致的返回格式

// 成功返回 // { // "success": true, // "data": { "id": 1, "name": "John" }, // "message": "User retrieved successfully" // } // 失败返回 // { // "success": false, // "error": { "code": 404, "message": "User not found" } // } // 统一的错误处理 async function fetchApi(url, options = {}) { try { const response = await fetch(url, options); const data = await response.json(); if (!data.success) { throw new Error(data.error?.message || 'Unknown error'); } return data.data; } catch (error) { console.error('API Error:', error); throw error; } } // 使用统一的错误处理 fetchApi('/api/v1/users') .then(data => console.log(data)) .catch(error => console.error(error)); 

分页和过滤

// 分页 fetch('/api/v1/users?page=1&limit=10') .then(response => response.json()) .then(data => console.log(data)); // 过滤 fetch('/api/v1/users?name=John&email=example.com') .then(response => response.json()) .then(data => console.log(data)); // 排序 fetch('/api/v1/users?sort=name&order=asc') .then(response => response.json()) .then(data => console.log(data)); 

API版本控制

// 使用URL路径进行版本控制 fetch('/api/v1/users') .then(response => response.json()) .then(data => console.log(data)); // 或使用请求头进行版本控制 fetch('/api/users', { headers: { 'Accept': 'application/vnd.example.v1+json' } }) .then(response => response.json()) .then(data => console.log(data)); 

API客户端封装

// api.js - 封装API客户端 class ApiClient { constructor(baseUrl) { this.baseUrl = baseUrl; } async request(endpoint, options = {}) { const url = `${this.baseUrl}${endpoint}`; const defaultOptions = { headers: { 'Content-Type': 'application/json' } }; const mergedOptions = { ...defaultOptions, ...options, headers: { ...defaultOptions.headers, ...options.headers } }; try { const response = await fetch(url, mergedOptions); const data = await response.json(); if (!data.success) { throw new Error(data.error?.message || 'Unknown error'); } return data.data; } catch (error) { console.error('API Error:', error); throw error; } } // 用户相关API getUsers(params = {}) { const queryString = new URLSearchParams(params).toString(); return this.request(`/users${queryString ? `?${queryString}` : ''}`); } getUser(id) { return this.request(`/users/${id}`); } createUser(user) { return this.request('/users', { method: 'POST', body: JSON.stringify(user) }); } updateUser(id, user) { return this.request(`/users/${id}`, { method: 'PUT', body: JSON.stringify(user) }); } deleteUser(id) { return this.request(`/users/${id}`, { method: 'DELETE' }); } } // 使用API客户端 const api = new ApiClient('https://api.example.com/v1'); // 获取用户列表 api.getUsers({ page: 1, limit: 10 }) .then(users => console.log(users)) .catch(error => console.error(error)); // 创建用户 api.createUser({ name: 'John', email: '[email protected]' }) .then(user => console.log(user)) .catch(error => console.error(error)); 

毒舌点评

API设计确实很重要,但我见过太多前端开发者把API设计的责任完全推给后端,自己只负责调用。你以为后端会自动设计出好的API?别做梦了!后端开发者可能不了解前端的需求,设计出来的API可能并不适合前端使用。

想象一下,当后端设计了一个返回格式不一致的API,前端需要写大量的代码来处理不同的返回格式,这会大大增加前端的开发工作量。

还有那些没有分页和过滤功能的API,当数据量很大时,前端会收到大量数据,导致应用变得很慢。

所以,前端开发者应该积极参与API设计,与后端开发者沟通,确保API设计符合前端的需求。

当然,API设计也不是越复杂越好。过于复杂的API设计会增加后端的开发成本,也会增加前端的学习成本。

最后,记住一句话:API设计的目的是为了方便使用,而不是为了炫技。如果你的API设计让使用者感到困惑,那你就失败了。

Read more

openclaw多agent对接飞书机器人

本文介绍了基于飞书的多Agent系统架构设计,通过OpenClaw Gateway实现飞书应用与AI Agent的对接。系统采用多Agent架构,每个飞书机器人对应独立的AI Agent,拥有专属的工作空间、知识库和模型配置。         本文可以参考的内容: * 多agent对接单个飞书账号 * openclaw多agent群聊 * 飞书机器人群聊 * 多agent数据隔离 * 多agent单独安装skills         隔离性说明: * 每个 Agent 的模型状态完全独立 * 每个 agent 对应一个飞书机器人 * 每个 agent 的技能单独安装维护 * 模型切换仅对当前会话生效(持久化到 Agent 配置) * 严格隔离:每个 Agent 独立 workspace 和 data 添加新的 agent # 添加agent openclaw agents add finance_agent #openclaw agents add code_agent # 设置身份

Modelsim仿真软件的,安装/破解/使用教程大全

仿真前言         作为一名FPGA工程师,在做FPGA开发时,使用仿真一定是最重要的,有些人喜欢写完代码直接上板子调试,根本不会做一点点仿真;如果是简单的逻辑代码,有十足的把握,那就不用仿真,可以直接上板子调试,但是,如果您是在做工程的开发,很多代码都是第一次编写调试,那么,代码的仿真是一定要做的,你要问我为啥,我个人觉得,每次把自己写完的代码,放到modelsim上面仿真看一下波形,就像考试的时候,拿着参考答案在做题一样的感觉,各个波形的变化你都会看的一清二楚,但是如果你用在线逻辑分析仪看RTL的仿真,那真的是太耗费时间;         我知道这个时候就会有人说了,Modelsima仿真有啥用呀,和下板子调试完全是两个概念,包括信号延迟,信号质量,眼图等都不一样,说的也对,但是实际情况是,这些人眼高手低,觉得仿真这种操作太麻烦;仿真虽然不能完全模拟真实的硬件信号,硬件延迟也没法准确仿真,但是他能让你在开发的时候,规避掉95%的因为代码引起的错误,这会让你在调试阶段节省很多时间;然后剩下的调试你必须 要在硬件调试时才会发现并且解决;        在调试阶段,FPGA为

宇树科技Go2机器人强化学习(RL)开发实操指南

宇树科技Go2机器人强化学习(RL)开发实操指南

在Go2机器人的RL开发中,环境配置、模型训练、效果验证与策略部署的实操步骤是核心环节。本文基于宇树科技官方文档及开源资源,以Isaac Gym和Isaac Lab两大主流仿真平台为核心,提供从环境搭建到实物部署的全流程操作步骤,覆盖关键命令与参数配置,帮助开发者快速落地RL开发。 一、基础准备:硬件与系统要求 在开始操作前,需确保硬件与系统满足RL开发的基础需求,避免后续因配置不足导致训练中断或性能瓶颈。 类别具体要求说明显卡NVIDIA RTX系列(显存≥8GB)需支持CUDA加速,Isaac Gym/Isaac Lab均依赖GPU进行仿真与训练操作系统Ubuntu 18.04/20.04/22.04推荐20.04版本,兼容性最佳,避免使用Windows系统(部分依赖不支持)显卡驱动525版本及以上需与CUDA版本匹配(如CUDA 11.3对应驱动≥465.19.01,CUDA 11.8对应驱动≥520.61.05)软件依赖Conda(

【无人机】无人机路径规划算法

【无人机】无人机路径规划算法

目录 一、引言:无人机与路径规划算法 二、路径规划算法基础 (一)定义与重要性 (二)规划目标与约束条件 三、常见路径规划算法详解 (一)A * 算法 (二)Dijkstra 算法 (三)RRT(快速扩展随机树)算法 (四)蚁群算法 四、算法应用实例与效果展示 (一)不同场景下的算法应用 (二)算法性能对比数据 五、算法的优化与发展趋势 (一)现有算法的优化策略 (二)结合新技术的发展方向 六、挑战与展望 (一)面临的技术挑战 (二)未来应用前景 七、结论 一、引言:无人机与路径规划算法 在科技飞速发展的今天,无人机作为一种极具创新性的技术产物,已深度融入我们生活的方方面面,