闭包适合实现前端请求限流器,核心是维护时间窗口内的调用计数和时间戳;基础令牌桶式按固定速率补充令牌,滑动窗口更精确避免边界突增,异步限流器支持Promise并维护等待队列,但前端限流仅作体验优化,关键接口必须后端校验。

闭包可以保存状态,天然适合实现前端请求限流器。核心思路是:用闭包维护一个时间窗口内的调用计数和时间戳,每次调用前判断是否超过阈值,未超则放行并更新状态,超了就拒绝或排队。
基础令牌桶式限流(简单可靠)
这是最常用、易理解的实现方式。闭包内缓存 剩余令牌数 和 上次补充时间,按固定速率(如每秒1个)恢复令牌。
- 初始化时设定最大令牌数(capacity)和补充速率(tokens per second)
- 每次调用前计算从上次补充到现在应新增的令牌,累加但不超过 capacity
- 有令牌则消耗1个并返回 true;否则返回 false,表示被限流
function createRateLimiter(capacity = 5, refillRate = 1) {
let tokens = capacity;
let lastRefill = Date.now();
<p>return function() {
const now = Date.now();
const elapsed = (now - lastRefill) / 1000; // 秒
tokens = Math.min(capacity, tokens + elapsed * refillRate);
lastRefill = now;</p><pre class="brush:php;toolbar:false;">if (tokens >= 1) {
tokens -= 1;
return true; // 允许请求
}
return false; // 拒绝}; }
const limiter = createRateLimiter(3, 2); // 最多3个,每0.5秒补1个 console.log(limiter()); // true console.log(limiter()); // true console.log(limiter()); // true console.log(limiter()); // false(暂无令牌)
滑动时间窗口限流(更精确)
相比固定窗口,它能避免“窗口边界突增”问题(比如整点瞬间涌入大量请求)。闭包内维护一个数组记录最近每次调用的时间戳,每次检查数组中在当前时间窗口(如60秒)内的请求数。
前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。
- 每次调用时先清理过期时间戳(早于 now - windowMs 的)
- 若剩余请求数
- 否则返回 false
支持 Promise 的异步限流器(适配 fetch / axios)
真实项目中常需包装 API 调用。闭包可封装成返回 Promise 的函数,被限流时自动延迟到下一个可用时机,不丢失请求。
立即学习“前端免费学习笔记(深入)”;
- 内部维护等待队列(数组存 resolve 函数)
- 允许时直接执行;拒绝时将 Promise 的 resolve 推入队列,并尝试在下次令牌可用时触发
- 用 setTimeout 或 requestIdleCallback 触发队列调度
实际使用建议与注意事项
- 前端限流仅作体验优化和防误操作,不能替代后端校验——攻击者可绕过 JS
- 对关键接口(如登录、支付),务必在服务端做严格限流(如 Redis + Lua)
- 考虑用户多标签页场景:单页闭包无法共享状态,如需全局控制,可配合 localStorage + storage 事件同步,或用 service worker 统一代理
- 调试时可在闭包内暴露 getState 方法,方便监控当前令牌/时间戳

















