# 绕口令与谜语查询:前端限流与防滥用实践
**接口**:绕口令与谜语查询(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)