大白话讲防抖与节流

744 阅读5分钟

字节跳动笔试题

什么是防抖和节流?有什么区别?如何实现?

故事的起源

在讲防抖和节流之前,我们先来引入本次的主人公。王老板、Chuck、汉堡店老板娘Judi

王老板呢,是一个年少有为的小伙子,整个人优秀的很,无不良嗜好,就是爱吃芝士汉堡(记住这一点,很重要)

Chuck呢,是老王雇来买汉堡的,其他什么也没有了,哦对了,Chuck每天是开着王老板的劳儿去的。

汉堡店老板娘Judi是Chuck的梦中情人,符合Chuck心中女神的所有标准,另外开店只是喜欢,已财富自由。

好了,故事到现在可以知道的是,王老板和Judi都是年少有为的人物,只有Chuck是一个穷光蛋。

王老板吃汉堡能吃到什么地步呢?只要有就可以一直吃下去~

Chuck每天的工作就是开个劳儿去汉堡店买汉堡。每买一个汉堡就开着劳儿来回跑一趟。

久而久之,王老板开始对Chuck不满,有一天王老板实在忍受不了了,就给Chuck说:“小伙子,不是我说你啊,你开我的劳儿,一趟只买一个,你就不能多买几个?一个还不够我塞牙份儿呢,而且这一趟的油钱、车辆的损耗都够我多吃几个汉堡🍔了?“

Chuck这小伙子脑子转的还算比较快,灵光一现给王老板提了一个方案:“先去买一个汉堡,然后等5分钟,如果5分钟内能做出来新的汉堡🍔,那就继续买,并重新倒计时5分钟。直到5分钟内做不出来新的汉堡了,那我就走了”。

王老板一听,心里想“这可以啊,这一下子能买回来好多呢!”,于是清了清嗓子说:“可以,你小子这方法真不错,以后每个月给你加2块钱薪水。”Chuck一听心里窃喜:“老王八蛋,我在乎的是你那2块钱吗?我在乎的是可以多和Judi待一会儿。”

第二天按照这个Chuck的这个方案执行了,可给Chuck高兴坏了,整整在店里和Judi待了一天。可晚上回去可给王老板愁坏了,我白天一直在苦苦的等你,一直没等到,晚上要睡觉了,你给我拉了一劳斯莱斯的芝!士!汉!堡!

Chuck一听事情不太对,赶紧说:“老板,那一个方案考虑不周,我又想到了一个新的方案。先去买一个汉堡,然后等一个小时,这一个小时内所有的汉堡我都买下来,然后我回来先让你吃,之后我再去。

王老板一听,仔细斟酌了一下,发现这样不仅可以多吃汉堡了,还可以省点油钱和保养费了。就说:“Chuck啊,不愧是我看中的人,这个方案我看行!明天就按照你说的这样去办!”

第二天Chuck按照这个方案,虽然说中途回去送了几次汉堡,都是基本上还是一整天都在和Judi一起,王老板也有吃不完的汉堡🍔了!

未完待续......

敲黑板划重点了

看完故事不过瘾啊?没关系,先把下面的东西看了,故事嘛,多的是!

以上出现的三位角色小伙伴们可能已经猜出来对应的角色是什么了。快验证一下你的猜想对不对。

王老板---服务端

Chuck---负责通信的,也就是跑腿的

Judi---客户端

防抖

所谓防抖,就是故事中的Chuck提出的第一个方案。其本质是,如果某一个功能在一个设置好的倒计时内被再次触发,那么倒计时重新开始,直到倒计时顺利结束

节流

所谓节流,就是故事中的Chuck提出的第二个方案。其本质是,某一个功能在触发后设置一个倒计时,倒计时结束后什么也不管,就直接执行,无论有结果没结果。

应用

啊说了这么多,那防抖和节流到底是用来干嘛的?

其实就是用来减少一些操作的频率降低一些开销

就拿百度的搜索框来说,如果我们每输入一个字符,就会向服务器请求一次,那么我们可以确定的是,服务器的压力会无与伦比的大。就像故事中,王老板再有钱,也顶不住Chuck那样开劳斯莱斯。

实现

下面我提供一个防抖和节流的demo

// 假定一个Ajax请求

function ajax() {
  ...
}

// 防抖
function debounce(func, delay) {
  let timer = null;
  return () => {
    if (timer) {
      // 说明之前设置过定时器,此时我们需要清除和重置定时器
      clearTimeout(timer); // 清除定时器
      timer = null;				 // 重置定时器
    }
    timer = setTimeout(() => { 
      // 重新设置定时器
      func();	// 能够执行到这里说明在我们的倒计时内并没有重新触发某些操作,我们是时候该执行Ajax了
      timer = null; // 执行完毕后,重置定时器
    }, delay)
  }
}
  
// 节流
function throttle(func, delay) {
  let timer = null;
  return () => {
    if (!timer) {
      // 如果未设置定时,那么我们在这里进行设置定时器
      setTimeout(() => {
        func(); // 定时结束,我们是时候该执行Ajax了
        timer = null; // 执行完毕后,重置定时器
      }, delay)
    }
  }
}
  
// How to use it ?
let deAjax = debounce(ajax, 5000); // 为一个函数生成防抖版的函数
let thAjax = throttle(ajax, 5000); // 为一个函数生成节流版的函数

写在最后

最近走红的博士致谢也让我想到了一些事情。思考了很多,也做了一些打算,准备建立一个前端的学习小组(二维码在下面),想尽自己的一些能力去帮助一些想要学习前端的朋友。

我是Chuck,一个不那么正经的热爱技术的前端仔。

非常愿意结交新的朋友,希望有幸能够成为你微信好友的一员。

IMG_3456.JPG

IMG_3455.JPG