字节跳动笔试题
什么是防抖和节流?有什么区别?如何实现?
故事的起源
在讲防抖和节流之前,我们先来引入本次的主人公。王老板、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,一个不那么正经的热爱技术的前端仔。
非常愿意结交新的朋友,希望有幸能够成为你微信好友的一员。