跳到正文

手写练习/异步控制

GitHub

手写节流 throttle

中等异步性能

代码实现

JavaScript27 行
// 时间戳版:第一次触发立即执行。
function throttle(fn, delay) {
    let lastTime = 0;

    return function (...args) {
        const now = Date.now();

        if (now - lastTime >= delay) {
            lastTime = now;
            fn.apply(this, args);
        }
    };
}

// 定时器版:第一次触发需要等待 delay 后执行。
function throttleWithTimer(fn, delay) {
    let timer = null;

    return function (...args) {
        if (timer) return;

        timer = setTimeout(() => {
            timer = null;
            fn.apply(this, args);
        }, delay);
    };
}

笔记记录

手写节流 throttle

是什么

节流的规则是:即使事件一直触发,回调在固定时间内也最多执行一次。

常见场景:

  • 滚动时计算页面位置
  • 拖拽时更新元素坐标
  • 持续点击时限制操作频率

时间戳版

闭包保存上一次执行时间 lastTime。每次触发时,只有当 now - lastTime >= delay 才执行,并更新 lastTime。

触发 -> 计算时间差 -> 未达 delay:忽略
                         -> 达到 delay:执行,更新 lastTime

这个版本的第一次触发会立即执行。

定时器版

闭包保存 timer。没有定时器时就启动一个,已经有定时器时直接忽略新触发;回调执行时把 timer 恢复为 null,让下一个时间窗可以开始。

这个版本的第一次触发会在 delay 毫秒后执行。

代码关键点

  • 时间戳版必须在执行时更新 lastTime,否则限频不会生效。
  • 当前时间使用 Date.now(),不是 Data.now()。
  • fn.apply(this, args) 的第一个参数是 this,第二个参数才是参数数组。
  • 两个实现使用不同函数名,避免后一个函数声明覆盖前一个。