防抖函数与节流函数

防抖函数与节流函数

本文写于 2020 年 6 月 1 日

今天看到了两个函数,防抖函数与节流函数。

这俩函数名字看起来是不是十分高端?

但是对于前端而言,这一年多的学习让我明白——不要望文生义,更不要望文生畏

那么,啥是防抖?啥是节流?

请先思考两个故事。

故事一:

首先想象我们回到了 25 年前,我们的网速还是在 18kb/s 。

这个时候我们访问了现代的淘宝,准备备战 618。

但是很不幸,因为网速过慢,我们在购买的时候迟迟没有反应,所以我们一次又一次的点击“立即购买”。

假设这个淘宝是平行空间的淘宝,他们没有做任何防止重复提交的技术。

那么我们的多次点击,将会把所有的请求全部上传!恭喜你,购买了 N 件同样的商品。

故事二:

如果我们有 10 部电梯和 10 个用户,这些用户会以 5 秒钟的间隔依次进入电梯。并且用户一旦进入电梯,电梯门就会关闭,不可停止。

那这个时候,10 个用户,就会乘着 10 个电梯,顺着相差 5 秒的电梯一起上行。

这也太浪费资源了!

1. 防抖

所谓防抖函数,就是当我们连续的调用 foo() 函数时,总是会中断之前的函数,然后立即执行最新的一次调用。

为啥要这么做呢?想想刚刚的电梯故事,多么的浪费资源!

但是如果这个故事发生在日常的生活中,我们会如何处理?

如果仅仅在短时间内,我们完全是可以按住“上行”按钮停住电梯门的。这样我们所有的人就能一起上行

这就是防抖。

防抖函数具体到底有哪些用途呢?

• 给按钮加函数防抖防止表单多次提交;
• 对于输入框连续输入进行 Ajax 验证时,用函数防抖能有效减少请求次数;
• 判断页面滑动何时停止。

2. 节流

节流规定一个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。

当我们在编写网页的时候,如果我们需要实现 DOM 拖拽功能,一般都会给 move 事件添加回调函数。

但是真正运行的时候我们会发现:每当元素稍微移动一点,就会触发了大量的回调函数,导致浏览器直接卡死。

除了 DOM 另外一个例子就是电影。

我们知道当 1 秒内连续播放 24 张以上的图片时,人的眼中这些图片就会形成一个连贯的动画。

所以在电影的播放中基本是以每秒 24 张的速度播放的,为什么不 500 张或更多是因为 24 张就可以满足人类视觉需求的时候,500 张就会显得很浪费资源。

对于函数节流,有如下几个场景:

• 游戏中的刷新率;
• DOM 元素拖拽;
• Canvas 画笔功能。

上代码:

/*
 * 防抖函数 debounce
 * fn 是执行的函数,wait 是防抖的时间间隔
 */
function debounce(fn, wait) {
  // 用一个变量来记录是否到达了防抖的时间
  let timer = null
  return function() {
    // 如果 timer 不为空,就会清除定时器,并且将 timer 清空
    if (timer) {
      clearTimeout(timer)
        timer = null
    }
    timer = setTimeout(() => fn(), wait)
  }
}
/*
 * 节流函数 throttle
 * fn 是执行的函数,gapTime 是节流的时间间隔
 */
function throttle(fn, gapTime) {
  let lastTime = null;
  return function () {
    let nowTime = + new Date()
    // 如果 lastTime 是 null,或者两次调用的时差超过了节流时间,才会执行函数
    if (!lastTime || nowTime - lastTime > gapTime) {
      fn();
      // 执行完毕后将时间同步
      lastTime = nowTime
    }
  }
}

这里我们可以看到,其实是 return 的用来操作 timerlastTime 的函数就是一个闭包。

如果不理解,可以不要外层的函数,直接将 timer 和 lastTime 放在全局作用域,再去尝试理解。

总结

一言以蔽之:函数防抖和函数节流,是在时间轴上控制函数的执行次数所用的函数。

(完)

原文地址:https://www.cnblogs.com/xhyccc/p/13261019.html