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

前端防抖、节流

这是一个非常经典的**抢购/秒杀**场景的前端优化问题。

### 结论:
1. **防抖(Debounce)绝对不适合**:防抖的机制是“等你疯狂点击停下来之后,才执行一次”。在抢购场景下,用户一定会疯狂连点,如果用防抖,用户的请求会一直被延迟,直到他点累了停下来才会发请求,那时候黄花菜都凉了。
2. **节流(Throttle)适用,但不够完美**:节流是“点第一下立刻执行,然后接下来的 1 秒内无论怎么点都忽略”。这能防止前端发送过多请求,但是如果接口响应很慢(比如超过 1 秒),1 秒后用户再点,又会发出一个重复请求。
3. **最适合的方案:异步状态锁(Loading 锁)+ UI 禁用**:核心逻辑是“**在当前接口没有返回结果之前,拒绝一切新的请求**”。

### 优化方案:给请求加上“异步锁”
相比于单纯依赖时间的节流,使用变量锁(推荐用 `useRef` 以避免重新渲染带来的闭包问题)来判断当前是否正在请求中,是最稳妥的。

我可以帮你修改 `handleLotteryClick`,引入一个 `lockRef`:

```tsx
// 使用 useRef 作为一个不受渲染周期影响的同步锁
const lockRef = useRef(false);

const handleLotteryClick = useCallback(
async (item: MemberDayFlashSaleItem) => {
// 1. 如果当前已经被锁住(说明上一个请求还没回来),直接拦截,什么都不做
if (lockRef.current) return;

// 2. 没上锁的话,立马加锁
lockRef.current = true;
const timestamp = Math.floor(Date.now() / 1000);

try {
const res = await claimMemberDayFlashSale({
activity_id: Number(item.activity_id),
session_id: Number(item.session_id),
welfare_id: Number(item.welfare_id),
timestamp: timestamp,
sign: buildMemberDayFlashSaleClaimSign({
activity_id: Number(item.activity_id),
session_id: Number(item.session_id),
welfare_id: Number(item.welfare_id),
timestamp: timestamp,
}),
});

if (res.code === 0) {
setPrizePopVisible(true);
setWinningPrizeInfo(item);
} else {
showToast(res.message || '活动火爆,请稍后尝试');
}
} catch (err) {
showToast('活动火爆,请稍后尝试');
} finally {
// 3. 无论成功还是失败,最后一定要把锁解开,允许下一次点击
// 如果想限制得更死,这里可以加个 setTimeout(..., 1000) 强制 1 秒后才能再次点击
lockRef.current = false;
}
},
[]
);
```

### 进阶优化(针对极致抢购场景):
如果在极端火爆的场景下,为了保护后端,我们可以把 **异步锁** 和 **节流** 结合起来。
在 `finally` 中不立刻解锁,而是强制等待一定时间(比如 500ms),也就是所谓的**强制冷却 CD**:

```tsx
} finally {
// 请求结束后,强制冷却 500ms 再解锁,相当于变相的节流
setTimeout(() => {
lockRef.current = false;
}, 500);
}
```

 

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

相关文章:

  • 3种技术概念验证方法:如何确保你的SHAP解释真正可靠?
  • python bandit
  • 别再让模型‘偏爱’多数类了:PyTorch中BCEWithLogitsLoss的weight和pos_weight参数实战指南
  • 量子编程语言:Q#与Qiskit框架的使用对比
  • ComfyUI IPAdapter完整指南:从零开始掌握AI图像风格迁移
  • FigmaCN中文插件:3分钟快速实现Figma界面汉化的完整指南
  • X-13ARIMA-SEATS时间序列季节调整软件的编译和使用
  • 答辩前三天才做 PPT?Paperxie AI PPT,把毕业论文答辩的焦虑全碾碎
  • 2026卫生专业技术资格考试考前押题卷TOP榜!冲刺提分必刷密卷测评 - 医考机构品牌测评专家
  • 小米手机录音机‘吃’掉了我的文件?深入Android/data/com.android.soundrecorder的完整避坑指南
  • 如何用300元预算打造专业级天文望远镜控制系统?OnStep开源方案全解析
  • 3个核心功能+5分钟部署:WarcraftHelper魔兽争霸III终极兼容性解决方案
  • UDS诊断进阶:拆解0x2C动态定义DID的三种用法与五大常见NRC应对策略
  • 构建生产级AI聊天机器人:PHP 9.0异步HTTP/2流式调用OpenAI + 自研RAG缓存层(仅需23行核心代码)
  • JBoltAI智能报价系统:从手工核算到标准化闭环
  • 思源宋体CN字体应用实战:3个关键场景提升你的设计效率
  • BiliTools跨平台工具箱:2026年最全面的B站资源下载解决方案
  • 2026最新!Python+AI零基础入门实战,代码直接抄,新手1个月逆袭
  • 别让答辩 PPT 毁了你的毕业高光!Paperxie AI 一键拿捏专业答辩演示稿
  • 10分钟完成黑苹果配置:OpCore Simplify图形化工具终极指南
  • TimescaleDB 2.26.4 版本发布:修复自 2.26.3 版本以来的多项错误,官方建议尽快升级
  • DeepSeek总结的MotherDuck四月产品综述:Duckling 监控、嵌入式 Dives、DuckLake 1.0 等
  • 【.NET 9边缘部署终极指南】:5大跨平台性能瓶颈+3步零配置优化,一线架构师压箱底实践
  • python safety
  • 从零掌握YimMenu:GTA5开源辅助工具深度配置与实战指南
  • OpCore-Simplify:15分钟完成专业级黑苹果配置的终极指南
  • 技术总监悄悄秀了一把 VS Code 神技,被我狠狠学到了!
  • 手把手教你修复JLink V9灯不亮问题:固件烧写全流程(附驱动安装避坑指南)
  • Windows Cleaner终极指南:3步轻松解决C盘爆红问题,让电脑重获新生
  • 实战指南:高效掌握Azure Kinect Sensor SDK的5个核心技巧