最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
uni-app中借助Promise封装异步请求 uni-app优雅处理API调用
时间:2026-06-16 09:57:58 编辑:袖梨 来源:一聚教程网
Promise封装是必须的,关键在于统一拦截、错误分流、自动token注入和loading管理;原生uni.request为回调式API,需封装解决嵌套深、难调试、无法await及错误处理分散等问题。
直接结论:Promise封装是必须的,但不能只套一层 Promise.resolve() 就算完事;关键在于统一拦截、错误分流、自动 token 注入和 loading 状态管理。
uni.request 为什么要用 Promise 封装?
原生 uni.request 是回调式 API,嵌套深、难调试、无法 await、错误处理分散。不封装就写业务,等于裸写异步逻辑——每次都要手动写 success/fail,catch 无处落脚,loading 开关靠人肉维护。
封装的核心价值不是“看起来更现代”,而是解决四个实际问题:
- 避免重复写
uni.showLoading()/uni.hideLoading() - 把
401、404、网络超时等错误归类处理,而不是每页都弹一遍模态框 - 自动读取并携带
token,避免每个接口都手动拼header.Authorization - 让
api/user/info这种调用能直接await,配合async setup()写法更自然
封装时 header 和 method 的常见陷阱
很多人封装后 POST 请求失败,返回 415 Unsupported Media Type,问题就出在 header 配置上。
注意以下三点:
-
method大小写敏感:"POST"不等于"post",uni-app 只认小写字符串 -
Content-Type必须按请求体类型匹配:传data: {a:1}且是 POST 时,应设{'Content-Type': 'application/json'};若传的是FormData,则必须用'multipart/form-data',且不能手动设 ——uni.request会自动处理 boundary - 小程序平台(如微信)对 header 字段名强制小写,
Authorization写成authorization也能通,但为保兼容,统一用首字母大写标准写法
示例中容易错写成:
if (method === 'post') { header['Content-Type'] = 'application/x-www-form-urlencoded' // ❌ 错!没序列化 data,后端收不到}
正确做法是:需要表单提交时,显式用 encodeURIComponent 拼接,或改用 uni.uploadFile 处理文件上传。
如何让封装支持 async/await 且不崩
Promise 封装本身不难,难的是在 fail 和 complete 中正确 reject / resolve,并确保异常可捕获。
关键点:
-
fail回调里必须reject(err),不能只console.log;否则await api.xxx().catch(...)永远进不去catch -
complete里不能做resolve或reject,它只负责清理(比如关 loading),否则会覆盖success/fail的结果 - 网络异常(如断网)触发的
fail,err.errMsg是"request:fail network error"这类字符串,不能直接当 HTTP 状态码用 - 务必在
try/catch外层包一层.catch(() => {}),防止未捕获的 Promise rejection 导致白屏(尤其在 Vue 3setup中)
最小可用封装骨架:
export default function request(params) { uni.showLoading({ title: '加载中' }) return new Promise((resolve, reject) => { uni.request({ url: BASE_URL + params.url, method: (params.method || 'GET').toLowerCase(), header: { ...params.header, ...(params.method?.toUpperCase() === 'POST' ? { 'Content-Type': 'application/json' } : {}), Authorization: uni.getStorageSync('token') ? `Bearer ${uni.getStorageSync('token')}` : '' }, data: params.data, success: res => { if (res.statusCode >= 200 && res.statusCode < 300) { resolve(res.data) } else { reject(new Error(`HTTP ${res.statusCode}`)) } }, fail: err => reject(err), complete: () => uni.hideLoading() }) })}
为什么你封装的 API 在某些页面里 await 不生效
现象:在 onLoad 里写 await api.getUser(),控制台报 Cannot read property 'then' of undefined。
根本原因只有两个:
- 封装函数没 return Promise(比如忘了写
return new Promise(...),或者在条件分支里漏了 return) - 调用时没加
await,却误以为函数本身会阻塞执行(JavaScript 异步本质不会变)
更隐蔽的问题是:Vue 2 选项式 API 中,data 初始化早于 onLoad,如果你在 data() 里就调用了封装函数,那它一定还没挂载完成,this 上下文为空,uni.getStorageSync 可能拿不到值 —— 这类问题不会报错,但 token 总是空。
建议始终把 API 调用放在生命周期钩子(onLoad、onShow)或事件回调中,而非 data 或 computed 里。
相关文章
- 伊莫星骑士支线任务如何完成 06-16
- 逆战未来深渊狂潮怎么玩 06-16
- 银河灰暗角落结局彩蛋触发方法分享 06-16
- 异能重组护盾流玩法攻略介绍说明 06-16
- 别拽了烤串师傅气味炸弹成就解锁攻略 06-16
- 银河灰暗角落暴击流玩法构筑分享 06-16