news 2026/4/16 2:22:21

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
前端项目中如何优雅地封装接口请求?一篇讲清 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,怎么写都能跑;但如果是实际业务项目,接口请求这部分越早规范,后续维护成本就越低。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 2:20:19

一套代码搞定推广全流程:GEO系统的20+核心功能模块详解与源码实现

AI搜索正在改变用户获取信息的方式。想让品牌出现在AI结果中?一套完整的GEO系统比想象中更重要。本文将拆解20核心功能模块,并给出关键源码片段。核心功能模块列表一、成本控制模块(3个)AI模型对接器 - 直接对接主流模型APIToken用…

作者头像 李华
网站建设 2026/4/16 2:19:15

保姆级教程:用Python+Matlab从零推导Panda机械臂的DH参数与正运动学

从零推导Panda机械臂:用Python和Matlab实现DH建模与正运动学验证 第一次接触机械臂运动学时,我被那些复杂的矩阵变换和参数定义搞得晕头转向。直到亲手用代码实现了一个完整的正运动学推导流程,才发现原来理解DH参数和坐标系变换可以如此直观…

作者头像 李华
网站建设 2026/4/16 2:18:15

LVGL界面布局总搞乱?5分钟搞懂盒子模型(附ESP32实战避坑指南)

LVGL界面布局总搞乱?5分钟搞懂盒子模型(附ESP32实战避坑指南) 刚接触LVGL的开发者经常会遇到这样的困惑:明明按照坐标计算好的按钮位置,实际显示却总是错位;嵌套的容器控件总是不按预期排列;滚动…

作者头像 李华
网站建设 2026/4/16 2:16:13

OpenAI紧急出招!GPT-5.4-Cyber抢先封锁安全漏洞,3000个高危Bug瞬间消失

OpenAI在硅谷巨头防御赛道上紧急加码,正式发布专为网络安全防御微调的强力模型GPT-5.4-Cyber。该模型不仅能在无源码环境下分析恶意软件,还凭借AI自动修复能力,交出一份“3000个高危漏洞已修复”的惊人成绩单。本周,科技界传来重磅…

作者头像 李华