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

前端项目中如何优雅地封装接口请求?一篇讲清 JS 请求管理思路

在前端开发中,接口请求几乎贯穿了所有业务页面。列表查询、详情回显、表单提交、删除操作,本质上都离不开请求后端接口。

很多项目在初期为了赶进度,往往会把请求直接写在页面里。页面一多,问题就慢慢暴露出来了:请求逻辑重复、接口地址分散、异常处理混乱、loading状态难维护,最后整个页面会变得越来越难改。

这篇文章只聊一件事:前端项目中如何更规范地处理接口请求


一、为什么不建议在页面里直接写请求

很多人一开始会这样写:

axios.post('/xxx/list',params).then(res=>{this.tableData=res.data})

这种写法短期看没问题,但一旦项目变大,很容易出现以下问题:

  1. 接口地址分散在各个页面中,不方便统一维护
  2. 页面里既有业务逻辑,又有请求细节,可读性差
  3. 相同接口调用方式重复书写,复用性差
  4. 后续如果要统一加 token、错误提示、请求拦截,改动范围会很大
  5. 页面代码越来越臃肿,不利于排查问题

所以,更推荐的方式是:把接口请求统一封装,再由页面按需调用


二、接口请求为什么要单独封装

在实际项目中,比较常见的做法是把接口统一放到api目录下,按模块拆分文件。页面只负责调用接口方法,不直接关心底层请求实现。

例如,我们可以这样封装一个接口方法:

importrequestfrom'@/utils/request'exportfunctiongetListApi(params,data){returnrequest({url:'/module/list',method:'post',params,data})}

这种方式的优势非常明显:

  1. 请求地址集中管理,方便维护
  2. 页面中调用语义更清晰
  3. 相同接口可以多处复用
  4. 方便统一处理请求头、鉴权、拦截器
  5. 页面代码更专注于业务逻辑本身

简单来说,接口封装的核心价值就是解耦
页面负责“用”,接口文件负责“管”。


三、一个项目里的接口请求通常分为哪几层

如果想让请求逻辑更清晰,通常可以分为三层:

1. 请求工具层

这一层一般是对axios的再次封装,主要负责:

  • 基础地址配置
  • 超时时间配置
  • 请求头统一处理
  • token 注入
  • 请求拦截和响应拦截
  • 通用错误提示

例如:

importaxiosfrom'axios'constservice=axios.create({baseURL:'/api',timeout:10000})exportdefaultservice

这一层通常不会写具体业务,只负责“底层能力”。


2. 接口模块层

这一层是把每个业务模块的接口单独封装成方法。

importrequestfrom'@/utils/request'exportfunctiongetListApi(params,data){returnrequest({url:'/module/list',method:'post',params,data})}exportfunctiondeleteApi(id){returnrequest({url:`/module/delete?id=${id}`,method:'get'})}

这一层的作用是:把具体业务接口抽象成可调用的方法


3. 页面调用层

这一层就是我们日常写页面逻辑的地方。页面只关心:

  • 什么时候发请求
  • 请求成功后如何赋值
  • 请求失败后如何提示
  • 是否展示loading

例如:

getList(){this.loading=truereturngetListApi(this.page,this.formData).then((res)=>{if(res.code===200){this.tableData=res.rows}else{this.$message.error(res.msg)}}).finally(()=>{this.loading=false})}

这种写法结构很清晰,职责也很明确。


四、为什么loading最好放在finally中处理

很多人在写接口请求时,习惯在then里关闭loading

getList(){this.loading=truegetListApi().then(res=>{this.loading=falsethis.tableData=res.rows})}

这并不是完全错误,但它有明显风险。

因为只有在请求成功进入then时,这段代码才会执行。如果出现下面这些情况:

  • 网络异常
  • 接口超时
  • 服务端报错
  • 请求被拦截器拦截
  • 业务处理过程中抛出异常

那么this.loading = false就可能执行不到,页面会一直处于加载状态。

因此,更稳妥的写法是把关闭loading放进finally

getList(){this.loading=truereturngetListApi().then((res)=>{if(res.code===200){this.tableData=res.rows}}).finally(()=>{this.loading=false})}

为什么推荐这样写?

因为finally的作用就是:
无论请求成功还是失败,只要这次 Promise 结束了,都会执行这里的代码。

这就非常适合放一些“收尾动作”,比如:

  • 关闭loading
  • 关闭弹层加载态
  • 清理临时状态
  • 还原按钮禁用状态

所以,页面中凡是涉及异步请求的状态收尾,优先考虑finally,会更稳。


五、一个更推荐的接口请求思路

在实际开发中,我更推荐采用这样的思路:

1. 所有请求都走统一请求工具

这样便于统一处理:

  • token
  • baseURL
  • 超时
  • 通用错误
  • 拦截器逻辑

2. 所有业务接口都单独封装方法

不要把接口地址散落在页面里。
页面应该调用方法,而不是直接拼请求配置。

3. 页面只负责业务数据处理

页面中最重要的是“业务表达”,而不是请求细节。

4. 所有异步状态收尾统一放到finally

尤其是:

  • loading
  • 按钮禁用状态
  • 上传遮罩层
  • 弹框中的处理中状态

这一步非常关键,能明显减少异步状态异常。


六、总结

前端接口请求,看起来只是“调一下接口”,但真正决定代码质量的,是请求背后的组织方式。

一个更规范的接口请求结构,通常具备这些特点:

  • 请求工具统一封装
  • 业务接口按模块统一管理
  • 页面调用逻辑清晰简单
  • loading状态有统一收尾
  • 页面不直接堆砌请求细节

如果只是小 demo,怎么写都能跑;但如果是实际业务项目,接口请求这部分越早规范,后续维护成本就越低。

前端开发写到最后,拼的往往不是“能不能实现”,而是“能不能持续维护”。
而接口请求的封装方式,恰恰就是最能拉开代码质量差距的地方之一。

http://www.jsqmd.com/news/647860/

相关文章:

  • 为什么说MetaFormer才是视觉任务的本质?从PoolFormer看架构设计的范式转移
  • 2026全网最全的AI软件测试面试题(含答案+文档)
  • Arduino IDE串口识别失败?别慌!可能是CH340驱动端口被占用了(附一键排查脚本)
  • 机械键盘连击终结者:KeyboardChatterBlocker 完全指南与实战配置
  • 告别位置编码!用SegFormer的Mix-FFN搞定语义分割中的多尺度输入难题
  • 【STM32-HAL库】RS485中断接收实战:基于STM32F103VET6的稳定通信方案
  • 【LeetCode Hot 100】 除自身以外数组的乘积(238题)多解法详解
  • 【仅限本周开放】多模态域适应私密工作坊实录:手把手复现ICML 2024 Oral论文《Cross-Modal Invariant Transport》完整Pipeline
  • 工业相机开发实战:埃科GigE相机SDK调用全流程解析(附代码示例)
  • 避坑指南:VLLM中CUDA Graphs捕获失败的5个常见原因及解决方案
  • 【保姆级】嵌入式工程师的Git第一课:从“硬件版本混乱“到“代码时光机“(环境搭建与核心概念详解)
  • 手把手教你用lspci和setpci排查PCIe设备性能瓶颈:从MaxPayloadSize到TLP传输优化
  • OCR大模型推理速度提升470%?揭秘2026奇点大会现场实测的8层量化蒸馏架构
  • STM32实战:FreeModbus移植避坑指南(基于正点原子F4库函数版)
  • vite8相对于vite7否更新哪些东西?
  • 基于LTspice的文氏桥振荡电路设计与频率稳定性优化
  • 从零开始DIY一个可调稳压电源:用LM317和XL4016搭建你的桌面实验神器
  • 脂肪族异氰酸酯市场:2026 - 2032年爆发式增长,年复合增长率(CAGR)为6.6%
  • 打破 “事后补救” 困局!西格电力防逆流方案,主动防控更安心
  • RHEL退出中国,一个开源时代的落幕
  • ICLR 2026在审论文SAM 3拆解:它的‘数据引擎’和‘记忆银行’是怎么搞定开放词汇歧义的?
  • pod均匀分布到不同拓扑域
  • 多版本Qt共存避坑指南:如何避免Anaconda3等软件与Qt开发环境冲突
  • 【保姆级】Git第二课:STM32日常开发实战——从“乱提交“到“原子化版本管理“(基础命令与规范详解)
  • SAM3 震撼来袭!手把手教你在 BitaHub 部署“语义级”智能隐私护盾
  • 收藏!大模型应用开发秋招面经(近半年实测,小白/程序员必看)
  • Zabbix数据库清理优化实战:如何调整Housekeeper参数避免告警风暴
  • 2026年热门的混凝土检查井/雨水检查井高口碑品牌推荐 - 品牌宣传支持者
  • OpenCore Legacy Patcher终极指南:4步让老Mac焕发新生
  • 终极指南:如何用OmenSuperHub彻底释放惠普OMEN游戏本性能