当前位置: 首页 > news >正文

038-API层架构设计

038 — API 层架构设计:从枚举定义到模块化 API 管理

简介

随着业务复杂度的增长,网络请求的管理方式直接影响项目的可维护性。MoneyTrack 采用了一套分层清晰的 API 架构:底层是单例 Axios 客户端(037 篇已述),中间层是枚举驱动的接口地址集中管理,上层是按业务域划分的模块化 API 文件。这套架构使得 30+ 个网络端点的查找、维护和调试变得井然有序,新增一个接口只需添加枚举值和对应方法,无需改动既有代码。

API 三层架构全景

🔗 HTTP 客户端

📋 枚举层 (单一数据源)

📦 API 模块层

📱 ViewModel 调用层

HomeViewModel.ets

BillViewModel.ets

UserViewModel.ets

Bill.ets
getBillList()

Asset.ets
getAssetList()

User.ets
login / logout / updateUserInfo

RequestUrlMap
30+ 端点枚举

Request.ets
Axios 单例 + 拦截器

核心知识点

1. API 枚举集中管理

将所有后端接口地址定义在统一的RequestUrlMap枚举中,实现接口地址的"单一数据源":

  • 避免硬编码:字符串散落在各文件中容易拼写错误,枚举统一管控。
  • 自文档化:枚举名即接口用途说明,一目了然。
  • 类型安全:配合 TypeScript 类型检查,修改地址时全局可控。

以下是 MoneyTrack 项目中RequestUrlMap枚举的完整展示(覆盖用户、家庭、账本、账单、资产五大模块):

exportenumRequestUrlMap{/** ===== 用户相关 ===== */USER_LOGIN='user/login',USER_LOGOUT='user/logout',USER_INFO='user/info',USER_MEMBERSHIP='user/membership',/** ===== 家庭相关 ===== */FAMILY_CREATE='family/create',FAMILY_JOIN='family/join',FAMILY_MEMBERS='family/members',FAMILY_LEAVE='family/leave',FAMILY_REMOVE_MEMBER='family/removeMember',/** ===== 账本相关 ===== */ACCOUNT_BOOK_LIST='accountBook/list',ACCOUNT_BOOK_CREATE='accountBook/create',ACCOUNT_BOOK_UPDATE='accountBook/update',ACCOUNT_BOOK_DELETE='accountBook/delete',ACCOUNT_BOOK_SWITCH='accountBook/switch',/** ===== 账单相关 ===== */BILL_LIST='bill/list',/** ===== 资产相关 ===== */ASSET_LIST='asset/list',}

2. 模块化 API 文件

按业务领域将 API 调用拆分到独立文件,每个文件只负责一个业务模块。采用类 + 单例导出模式,既保持了面向对象的封装性,又方便上层调用:

// Asset.ets — 资产模块 APIclassAssetApis{publicgetAssetList(ownerId?:number):Promise<BaseResponse>{constparams:Record<string,Object>={};if(ownerId!==undefined){params['ownerId']=ownerId;}returnrequest.get(RequestUrlMap.ASSET_LIST,{params});}}constinstance=newAssetApis();export{instanceasAssetApis};
// User.ets — 用户模块 APIclassUserApis{publiclogin(params?:UserLoginReq):Promise<BaseResponse>{returnrequest.get(RequestUrlMap.USER_LOGIN,{params});}publiclogout():Promise<BaseResponse>{returnrequest.get(RequestUrlMap.USER_LOGOUT);}publicupdateUserInfo(data:UpdateUserInfoReq):Promise<BaseResponse>{returnrequest.put(RequestUrlMap.USER_INFO,data);}publicsubscribeMembership():Promise<BaseResponse>{returnrequest.post(RequestUrlMap.USER_MEMBERSHIP);}publicgetMembershipInfo():Promise<MembershipInfoResp>{returnrequest.get(RequestUrlMap.USER_MEMBERSHIP);}}constinstance=newUserApis();export{instanceasUserApis};

3. 类型安全的泛型约束

每个 API 都明确定义了请求参数类型和响应数据类型,利用 TypeScript 泛型在编译期捕获类型错误:

// 定义泛型响应结构exportinterfaceBaseResponse<T=any>{code:number;message:string;data:T;}// 在 API 方法中使用泛型约束classBillApis{publicgetBillList(memberId?:number):Promise<BaseResponse<BillItem[]>>{constparams:Record<string,Object>={};if(memberId!==undefined){params['memberId']=memberId;}returnrequest.get(RequestUrlMap.BILL_LIST,{params});}}

当后端返回的数据结构发生变化时,只需修改泛型类型定义,所有调用方都会收到编译警告,极大降低回归风险。

4. API 版本管理

URL 中携带版本号是管理 API 演进的通行做法。在request层通过 baseURL 携带主版本号,或通过拦截器自动注入版本参数:

// 方案一:baseURL 携带版本号constinstance=axios.create({baseURL:'https://api.moneytrack.com/v2/',// 整个应用使用 v2 版本});// 方案二:按模块在 API 路径中指定版本enumRequestUrlMap{USER_LOGIN_V1='v1/user/login',USER_LOGIN_V2='v2/user/login',// 渐进式升级}
特性枚举集中管理硬编码字符串
可维护性一处修改全局生效四处查找替换
自文档化枚举名说明用途需额外注释
类型检查编译期检测运行时才能发现
协作效率新人快速了解接口需翻阅文档

最佳实践

  1. 枚举命名规范:采用模块_动作格式(如USER_LOGINBILL_LIST),按模块分组并用注释分隔,方便快速定位。
  2. API 文件粒度:一个业务模块一个文件,文件内只导出类实例(单例),避免命名空间污染。
  3. 类型优先:先定义请求/响应的 TypeScript 接口,再实现 API 方法。让类型定义驱动开发流程。
  4. 渐进式版本升级:新旧版本接口枚举共存,逐个模块迁移,避免大版本一次性升级的风险。

推荐参考文档

  • TypeScript 枚举与泛型文档
  • RESTful API 版本管理最佳实践
http://www.cnnetsun.cn/news/3528498.html

相关文章:

  • 基于WebAssembly的位图矢量化技术实现机制与工程实践
  • 【闲聊】如何睡得既少做得还多(方法)
  • Switch2Cursor完整指南:JetBrains与Cursor编辑器高效切换终极方案
  • 2026年7月市场上最具竞争力的全球4强企业建站系统最新测评报告,含零代码、低代码、AI+编程
  • PDF批注、溯源、跨页推理全打通:Kimi企业级PDF工作流(附可直接复用的12条系统级指令集)
  • Illustrator脚本大全:30+个自动化工具让你的设计效率飙升
  • 3个步骤,让Wand游戏修改器变身专业版:开源增强工具完全指南
  • AI 视频制作教程 2026:脚本→分镜→生成→剪辑全流程与工具清单
  • keil中出现encountered an improper argument解决办法
  • TMS320F2838x内存保护与错误处理:从ECC原理到安全关键系统设计
  • 千瓦级ACDC电源多模式效率优化与数字控制技术解析
  • Android CLI 完全指南:从入门到精通
  • 从零构建C++游戏框架:核心架构、模块设计与高阶实现技巧
  • AM62L RTI窗口看门狗与DMTIMER定时器寄存器配置实战指南
  • MoodSelector 心情组件:@Link 双向绑定实现父子通信
  • 无限画布制作沙发换装视频,太有创意了!
  • Android RecyclerView核心原理与优化实践
  • WINCE系统启动自动运行程序的实现方案
  • Python元类:类的构造者
  • 除了image和NGS-base,也许空间转录组平台该按分辨率划分:单细胞、亚细胞、多细胞
  • 从零掌握Locust:Python分布式性能测试实战指南
  • Android定时任务:Handler与Timer的深度对比与实践
  • Agent开发的难点是什么呢?
  • NCF实战:工业级神经协同过滤从零落地指南
  • 深入解析UART/IrDA/CIR控制器寄存器:从配置到多模式通信实战
  • 【单片机毕业设计】基于 51/STM32 单片机的车载酒精检测与发动机断电预警系统设计,基于 51/STM32 单片机的 MQ-3 酒精浓度声光语音报警装置开发(020502)
  • 【Bug已解决】Codex Desktop: project rename dialog closes when sidebar auto-hides in hover mode 解决方案
  • 2026年语音识别平台哪个好?这3个实用选择标准帮你挑到合适的
  • TI微控制器GPTM定时器寄存器级配置与PWM应用实战
  • Android代码混淆与优化:ProGuard/R8实战指南