前端面试之防抖节流(二)

前言

大家好,作者之前在防抖节流(一)中介绍了一下防抖节流中的防抖,详细阐述了它的应用以及实现代码,这篇文章将要介绍一下它的好兄弟--节流。

什么是节流

那么什么是节流呢?

节流(throttle)是通过限制函数执行的频率,在一定时间内只执行一次,以减少资源消耗或优化性能。

它在页面中的效果是这样的:

注意看控制台:在用户输入时,无论用户输入的频率如何,节流帮我们控制了让输入框内容的输出只有在一秒内才能输出一次。

大家都打过fps游戏吧,不论你的鼠标左键点击多少次,最终枪械的输出次数只取决于它的射速,这就类似于节流的效果。

为什么要节流?

那么为什么要节流呢?

有一些典型的应用场景:

  1. 滚动事件(scroll)

    • 问题:滚动页面时会高频触发 scroll 事件,如果回调函数涉及 DOM 计算、动画等操作,会导致卡顿。
    • 节流作用:限制为每 100ms 执行一次,减少不必要的计算。
  2. 窗口调整(resize)

    • 问题:拖拽调整窗口大小时,resize 事件会连续触发,若回调函数需要重新布局页面,可能引发性能瓶颈。
    • 节流作用:确保只在调整结束后或固定间隔执行一次布局计算。
  3. 按钮防连点(点击提交)

    • 问题:用户快速点击提交按钮时,可能发送多次重复请求。
    • 节流作用:限制点击间隔(如 1 秒内只能提交一次),避免重复请求。

节流的实现

接下来看看节流的实现吧

节流的实现代码如下:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <input type="text" id="inputC" />
    <script>
        let inputC = document.getElementById('inputC');
        const ajax = function(content) { //被节流的函数
            console.log("ajax request" + content)
        }

        function throttle(fn,delay) {
            let last,
                deferTimer;

            return function(args){
                let that = this; 
                let now = + new Date(); 
                if (last && now < last + delay){
                clearTimeout(deferTimer);
                deferTimer = setTimeout(function() {
                    last = now;
                    fn.call(that,args);
                },delay);
            } else{
                last = now;
                fn.call(that,args);
            }
        }
        }

        let throttleAjax = throttle(ajax,1000);

        inputC.addEventListener('keyup',function(e) {
            throttleAjax(e.target.value);
        })
    </script>
</body>
</html>

了解过上一篇介绍防抖的实现代码的朋友们看到这里会发现,防抖的代码结构和节流很类似,是的,它们都是用高阶函数实现+闭包特性实现的,下面是详细解读

  • (一)定义ajax函数
js 复制代码
const ajax = function(content) { //被节流的函数
    console.log("ajax request" + content)
}

ajax 是一个模拟的请求函数,在实际应用中可能是 fetchXMLHttpRequest 请求。


  • (二)实现throttle节流函数
js 复制代码
function throttle(fn, delay) {
    let last, deferTimer; // 记录上次执行时间、定时器

    return function(args) {
        let that = this; // 保存 this 指向
        let now = +new Date(); // 当前时间戳

        if (last && now < last + delay) { // 如果在节流间隔内
            clearTimeout(deferTimer); // 清除之前的定时器
            deferTimer = setTimeout(function() {
                last = now; // 更新时间戳
                fn.call(that, args); // 执行函数
            }, delay);
        } else { // 如果不在节流间隔内
            last = now; // 更新时间戳
            fn.call(that, args); // 立即执行函数
        }
    }
}

这里是节流实现的核心部分:

  1. last :记录上次执行 fn 的时间戳。

  2. deferTimer :存储 setTimeout 的 ID,用于清除未执行的延迟调用。

  3. now :获取当前时间戳(+new Date() 转化为number类型,方便等下计算)。

  4. 节流判断

if (last && now < last + delay)

如果 last 存在(非首次调用),并且当前时间距离上次调用时间小于 delay(仍在节流间隔内),则:

go 复制代码
清除之前的 `setTimeout`(避免堆积多个延迟调用)。
重新设置一个 `setTimeout`,在 `delay` 时间后执行 `fn`。

else

go 复制代码
如果不在节流间隔内(首次调用或间隔已过),则:
    立即执行 `fn`,并更新 `last` 时间戳。

  • (三)应用节流函数
js 复制代码
let throttleAjax = throttle(ajax, 1000); // 1秒内只执行一次
inputC.addEventListener('keyup', function(e) {
    throttleAjax(e.target.value); // 传入输入框的值
});

throttle(ajax, 1000) :生成一个节流版本的 ajax 函数,确保 1 秒内最多执行一次。

keyup 事件监听

go 复制代码
每次输入时,调用 `throttleAjax`,传入输入框的值。

如果用户在 1 秒内连续输入,`ajax` 不会立即触发,而是:

    第一次输入时立即执行 `ajax`。
    后续输入会进入 `setTimeout`,并在 1 秒后执行(如果期间没有新的输入)。

执行流程示例

假设用户快速输入 abc

  1. 输入 a

    • last 未定义 → 立即执行 ajax("a"),并记录 last = now
  2. 输入 b(0.5 秒后)

    • now < last + 1000(仍在 1 秒内)→ 清除之前的 setTimeout,重新设置 1 秒后执行 ajax("b")
  3. 输入 c(0.8 秒后)

    • now < last + 1000(仍在 1 秒内)→ 再次清除 setTimeout,重新设置 1 秒后执行 ajax("c")
  4. 最终结果

    • ajax("a") 立即执行。
    • ajax("c") 在 1 秒后执行(b 被覆盖)。

总结

上面就是关于节流知识的全部内容了,希望该文章对你有帮助!

相关推荐
dy17172 小时前
element-plus表格默认展开有子的数据
前端·javascript·vue.js
2501_915918416 小时前
Web 前端可视化开发工具对比 低代码平台、可视化搭建工具、前端可视化编辑器与在线可视化开发环境的实战分析
前端·低代码·ios·小程序·uni-app·编辑器·iphone
程序员的世界你不懂7 小时前
【Flask】测试平台开发,新增说明书编写和展示功能 第二十三篇
java·前端·数据库
索迪迈科技7 小时前
网络请求库——Axios库深度解析
前端·网络·vue.js·北京百思可瑞教育·百思可瑞教育
在未来等你7 小时前
Kafka面试精讲 Day 13:故障检测与自动恢复
大数据·分布式·面试·kafka·消息队列
gnip7 小时前
JavaScript二叉树相关概念
前端
一朵梨花压海棠go8 小时前
html+js实现表格本地筛选
开发语言·javascript·html·ecmascript
attitude.x8 小时前
PyTorch 动态图的灵活性与实用技巧
前端·人工智能·深度学习
β添砖java8 小时前
CSS3核心技术
前端·css·css3
空山新雨(大队长)8 小时前
HTML第八课:HTML4和HTML5的区别
前端·html·html5