浅析 JavaScript 防抖和节流
防抖和节流都是为了解决短时间内大量触发某函数而导致的性能问题,比如触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象。但二者应对的业务需求不一样,所以实现的原理也不一样。
防抖(debounce)
什么是防抖
在事件被触发n秒后再执行回调函数,如果在这n秒内又被触发,则重新计时。
应用场景
(1) 用户在输入框中连续输入一串字符后,只会在输入完后去执行最后一次的查询ajax请求,这样可以有效减少请求次数,节约请求资源;
(2) window的resize、scroll事件,不断地调整浏览器的窗口大小、或者滚动时会触发对应事件,防抖让其只触发一次;
实现
简易版
ES5
1 | function debounce(fun, delay) { |
ES6
1 | // func是用户传入需要防抖的函数 |
简单版的防抖,但是有缺陷,这个防抖只能在最后调用。一般的防抖会有immediate选项,表示是否立即调用。
这两者的区别:
- 例如在搜索引擎搜索问题的时候,我们当然是希望用户输入完最后一个字才调用查询接口,这个时候适用延迟执行的防抖函数,它总是在一连串(间隔小于wait的)函数触发之后调用。
- 例如用户给interviewMap点star的时候,我们希望用户点第一下的时候就去调用接口,并且成功之后改变star按钮的样子,用户就可以立马得到反馈是否star成功了,这个情况适用立即执行的防抖函数,它总是在第一次调用,并且下一次调用必须与前一次调用的时间间隔大于wait才会触发。
带有立即执行选项的防抖函数
1 | // 这个是用来获取当前时间戳的 |
节流(throttle)
什么是节流
规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。
应用场景
鼠标连续不断地触发某事件(如点击),只在单位时间内只触发一次;
在页面的无限加载场景下,需要用户在滚动页面时,每隔一段时间发一次 ajax 请求,而不是在用户停下滚动页面操作时才去请求数据;
监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断;
实现
1 | function throttle(fn, interval = 300) { |
另一个版本:
1 | function throttle(fun, delay) { |
区别
效果
函数防抖是某一段时间内只执行一次。
函数节流是间隔时间执行,不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数。
原理
防抖是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,都会清除当前的 timer 然后重新设置超时调用,即重新计时。这样一来,只有最后一次操作能被触发。
节流是通过判断是否到达一定时间来触发函数,若没到规定时间则使用计时器延后,而下一次事件则会重新设定计时器。
参考
详谈js防抖和节流
【面试篇】寒冬求职季之你必须要懂的原生JS(上) - 防抖和节流的区别是什么?防抖和节流的实现。
InterviewMap 防抖、节流
函数节流与函数防抖
7分钟理解JS的节流、防抖及使用场景