技术博客
绕口令与谜语查询:前端限流与防滥用实践

绕口令与谜语查询:前端限流与防滥用实践

作者: 万维易源
2026-09-03
前端限流防抖防滥用频率上限
# 绕口令与谜语查询:前端限流与防滥用实践 **接口**:绕口令与谜语查询(apiCode=1623)· 接入点 1623-1 / 1623-2|**是否免费**:免费(含使用档次限制)|**返回格式**:JSON|**适用人群**:前端、小程序、H5 开发者|**阅读时间**:约 6 分钟 ## 核心要点 - 免费接口有档次限制,**前端是滥用高发地**(按钮连点、轮询、多人同屏)。 - 三道防线:按钮防抖、单用户频率上限、失败兜底文案。 - 前端限流只能「减轻」,不能「替代」后端缓存——两者配合见[本地缓存策略](https://www.showapi.com/guides/tongue-riddle-cache-tier-1623)。 ## Why:前端不节流,额度秒没 一个「换一条」按钮如果没防抖,用户连点 10 下就打 10 次接口;课堂大屏几十人同时刷新,免费档位瞬间打满。前端限流是把「无意义重复请求」挡在用户侧的低成本手段。 ## What:三道防线 | 防线 | 作用 | 实现 | |------|------|------| | 按钮防抖 | 防连点 | 点击后禁用 N 秒 | | 单用户频率上限 | 防轮询/刷 | 前端计数 + 时间窗 | | 失败兜底 | 防雪崩 | 限流/失败时友好提示,不静默重试 | ## How:防抖 + 频率上限(前端 JS) ```javascript // 防抖:点击后 1.5s 内禁止再次触发 let lastCall = 0; const MIN_INTERVAL = 1500; async function onNext() { const now = Date.now(); if (now - lastCall < MIN_INTERVAL) { hint("别急,稍等一下再换~"); return; } lastCall = now; btn.disabled = true; try { const list = await (await fetch("/api/twister")).json(); render(list); } catch (e) { hint("暂时加载失败,请稍后再试"); } finally { setTimeout(() => (btn.disabled = false), MIN_INTERVAL); } } // 单用户频率上限(滑动窗口,示例:1 分钟最多 20 次) const WINDOW = 60_000, MAX = 20; const calls = []; function allowCall() { const t = Date.now(); while (calls.length && t - calls[0] > WINDOW) calls.shift(); if (calls.length >= MAX) return false; calls.push(t); return true; } ``` ## 返回示例与解析 限流发生在前端,不消耗接口额度;真正打到接口的请求返回结构见[返回字段全解](https://www.showapi.com/guides/tongue-riddle-response-fields-1623)。 ## 进阶 / 边界 - **防抖 ≠ 不调用**:防抖只合并「短时间内重复」,首次点击仍会调接口;配合后端缓存才能彻底省量。 - **课堂/大屏**:人多时仅靠前端限流不够,必须「课前取数 + 静态资源」,见[教育场景](https://www.showapi.com/guides/tongue-riddle-edu-scenario-1623) 与[H5 小游戏](https://www.showapi.com/guides/tongue-riddle-h5-game-1623)。 - **失败不要再猛重试**:限流/档位失败时给用户友好提示,指数退避由后端处理(见[错误处理](https://www.showapi.com/guides/tongue-riddle-error-handling-1623))。 - AppKey 不要进前端,见[H5 小游戏后端取数](https://www.showapi.com/guides/tongue-riddle-h5-game-1623)。 ## FAQ **Q1:前端限流能完全防住滥用吗?** A:不能。前端代码可被绕过,它是「减轻」手段;真正限流与缓存应放在后端,配合[本地缓存策略](https://www.showapi.com/guides/tongue-riddle-cache-tier-1623)。 **Q2:防抖间隔设多少?** A:按体验与额度权衡,示例 1.5s;课堂场景建议更长或改为「课前一次性取数」。 **Q3:频率上限会误伤正常用户吗?** A:会,窗口/上限要宽松些;更稳妥是后端按用户标识限流,前端只做基础防抖。 **Q4:失败拼命重试为何不好?** A:会放大流量、加速触发档位限制,形成雪崩;应友好提示 + 后端退避。 **Q5:小程序里怎么做?** A:`wx.request` 前加同样的防抖/窗口判断;AppKey 留在开发者服务端。 ## 下一步阅读 - [绕口令与谜语查询:免费档位下的调用纪律与本地缓存策略](https://www.showapi.com/guides/tongue-riddle-cache-tier-1623) - [绕口令与谜语查询:错误处理与 ret_code 排查](https://www.showapi.com/guides/tongue-riddle-error-handling-1623) - [绕口令与谜语查询:做一个 H5 绕口令/谜语小游戏](https://www.showapi.com/guides/tongue-riddle-h5-game-1623) - **本系列共 12 篇**:查看[绕口令与谜语查询指南总目录](https://www.showapi.com/guides/tongue-riddle-guides-1623)