目录
[1. 请求计数器(requestCount)](#1. 请求计数器(requestCount))
[2. 延迟隐藏定时器(关键创新)](#2. 延迟隐藏定时器(关键创新))
[3. 100ms缓冲期的重要意义](#3. 100ms缓冲期的重要意义)
// 典型问题代码
if (requestStart) {
wx.showLoading();
}
requestComplete() {
wx.hideLoading(); // 快速切换导致闪烁
}
一、问题背景:闪烁现象的产生
在小程序开发中,当多个网络请求快速连续触发时,使用wx.showLoading()
和wx.hideLoading()
控制加载提示会出现闪烁问题:
闪烁原因:
-
请求A完成 → 隐藏Loading
-
请求B开始 → 立即显示Loading
-
用户视觉感知:加载提示快速消失又出现 → 界面闪烁
二、完整解决方案代码
let requestCount = 0; // 全局请求计数器
let timerId = null; // 定时器ID
// 请求开始时
// 使用定时器防止loading闪烁 清除上一次的定时器
if (timerId) {
clearTimeout(timerId);
timerId = null;
}
if (loading) {
requestCount++;
if (requestCount === 1) {
wx.showLoading({ title: "加载中...", mask: true });
}
}
// 请求完成时
complete: function (params) {
// 处理loading隐藏
if (loading) {
requestCount--;
timerId = setTimeout(() => {
if (requestCount <= 0) {
requestCount = 0; // 确保不会为负数
wx.hideLoading();
// 清除定时器{最后一次请求}
clearTimeout(timerId);
timerId = null;
}
}, 500); // 500ms延迟,防止快速连续请求造成闪烁
}
},
三、核心防闪烁机制解析
1. 请求计数器(requestCount)
// 请求开始
requestCount++; // 增加计数
// 请求完成
requestCount--; // 减少计数
-
作用:合并多个请求状态
-
原理:
-
当
requestCount > 0
时保持Loading显示 -
只有归零时才允许隐藏
-
-
优势:避免单请求完成就隐藏的问题
2. 延迟隐藏定时器(关键创新)
if (timerId) clearTimeout(timerId); // 取消前次待执行操作
timerId = setTimeout(() => {
// 最终检查
}, 100);
-
双重保护机制:
-
clearTimeout
:中断前序未执行的隐藏操作 -
setTimeout
:延迟100ms执行最终状态检查
-
3. 100ms缓冲期的重要意义
时间点 | 无定时器方案 | 有定时器方案 |
---|---|---|
请求B完成 | 立即隐藏Loading | 计划100ms后隐藏 |
请求C开始(50ms) | 立即显示 → 闪烁 | 清除隐藏计划 → 保持显示 |
最终效果 | 闪烁 | 持续平稳显示 |
四、关键场景对比分析
场景1:连续快速请求

场景2:网络波动请求

五、为什么简化方案不行?
问题代码:
complete: function() {
if (loading) {
requestCount--;
if (requestCount <= 0) {
wx.hideLoading(); // 立即隐藏
}
}
}
致命缺陷:
-
在快速连续请求场景下:
-
请求B完成 → 立即隐藏
-
请求C开始 → 立即显示
-
间隔可能小于50ms → 人眼可感知闪烁
-
-
网络波动时:
-
请求失败重试 → 显示/隐藏频繁切换
-
用户体验割裂
-
六、设计思想总结
-
状态聚合:通过计数器合并请求状态
-
延迟响应:100ms缓冲期观察后续请求
-
操作可中断 :
clearTimeout
保证只响应最终状态 -
临界值保护 :
requestCount = 0
防止负数
防抖思想应用:这种模式本质是前端防抖(debounce)技术的变种,将高频的状态变更合并为单次稳定操作。100ms延迟经过实践验证,在用户体验和响应速度间达到最佳平衡。