uni.request 的 complete 回调必须收口 hideloading,因超时、ssl 错误等不触发 success/fail;showloading 需在 request 前调用;loading 应按需控制,支持 loading: false 和 loadingtext 自定义;h5 与小程序需分平台处理;防重需绑定请求实例而非页面生命周期。

uni.request 的 complete 回调必须收口 hideLoading
小程序端 loading 卡死的根源,90% 出在只在 success 或 fail 里调 uni.hideLoading()。网络超时、SSL 错误、域名未配置、请求被拦截——这些都不会触发 success 或 fail,但一定会进 complete。
正确做法是:所有请求封装必须把 uni.hideLoading() 放在 complete 里,且仅放这里。哪怕你用了 Promise/async-await,也不能依赖 try/catch 去 hide,因为 catch 不捕获超时或 DNS 失败。
-
uni.showLoading()必须在uni.request()调用前执行,否则有概率闪一下就消失(小程序渲染时机敏感) - 不要用全局布尔变量(如
isLoading = true)控制状态——并发请求会互相覆盖 - 如果封装层用了
Promise,complete里 hide 后再 resolve/reject,顺序不能颠倒
loading 开关必须支持按需控制,不能全量开启
轮询心跳、静默上传头像、下拉刷新重试、预加载资源——这些接口不该弹出 loading。硬编码统一 show 是反模式,业务层必须能显式关闭。
推荐参数设计:params.loading !== false 判断是否启用,params.loadingText 自定义文案。默认为 true,既兼容老代码,又避免漏配。
- 传
{ loading: false }就不 show,传{ loadingText: '提交中...' }就替换默认文案 - 别用字符串开关(如
loading: 'off'),类型易错,ts 类型提示弱 - 小程序真机调试时,
loadingText超过 7 个汉字可能被截断,建议控制在 6 字以内
H5 和小程序端 loading 行为差异必须隔离处理
uni.showLoading 在 H5 是 DOM 模拟实现,z-index 容易被 uView 导航栏、自定义 cover-view、router-view 动态插入顺序干扰;小程序则是原生 toast 层,层级固定但受 "enablePullDownRefresh": true 影响——开启下拉后,fixed 层会被压到下拉动画之下。
解决方案不是“统一一套样式”,而是分平台条件判断:
- 小程序端直接用
uni.showLoading,不 hack z-index - H5 端优先用自定义组件(v-if 控制 + pointer-events: none 遮罩),避开 DOM 注入时机问题
- 检查
pages.json中当前页面是否启用了下拉刷新,若启用,H5 下应禁用 loading 或改用骨架屏
防重逻辑必须绑定请求实例,而非页面生命周期
用户快速点击按钮多次,会触发多个请求,但 loading 只该显示一次。常见错误是用 onLoad 里设个 flag,结果不同请求共用一个 flag,后发请求把前一个的 loading 给提前 hide 了。
正确做法是:每个请求独立计算是否 show,靠参数和闭包隔离状态。
- showLoading 前加时间戳或 Symbol 标记,complete 里只 hide 当前请求对应的 loading(如果用了自定义组件)
- 若坚持用
uni.showLoading,则 rely on 它的“同时间只允许一个”特性——只要确保不重复调用 show 就行,靠参数开关 + 请求前判断即可 - 别在
onUnload或onHide里强制 hide,可能干扰正在进行的请求
loading: false、所有平台都验证过 z-index 冲突点——漏掉任意一环,上线后就是偶发卡死或白屏。











