前言
在前端开发过程中,经常会遇到一些触发频率极高的按钮、操作、交互事件等等。如果我们不对这些事件做处理, 不但对于浏览器的压力,以及对后端接口的压力十分大,非常容易出现浏览器崩溃,接口卡死等等情况,这个时候我们就需要 借用防抖与节流优化对应的事件
节流与防抖的本质
这两个东西都以闭包
的形式存在
通过对事件的回调函数进行缓存,使用定时器进行控制事件的触发频率。
例子
先说一个在后台管理系统常见的例子,很多后台管理系统会出现AutoComplete自动完成输入框
为用户提供输入建议,这种输入框会监听change事件
,
如果不做限制的话,我们输入十个字符就会调用接口十次
在运行的时候会发现存在一个问题,这个接口调用频率太高了,同理的还有监听scrollTop,抢购按钮等
debounce 防抖
防抖:在设定的时间内频繁触发函数时,以最后一个
函数为准。
防抖其实就是记录这次执行函数,放入定时器中,如果在设定时间内再次出现就清除定时器,重新设置定时器。
简单实现:
function debounce (fn, delay = 1000) {
// 设置定时器
let timer = null
return function () {
const context = this
const args = arguments
if (timer) {
// 有定时器就清除
clearTimeout(timer)
}
// 重新记录函数
timer = setTimeout(function () {
fn.apply(context, args)
}, delay)
}
}
Throttle 节流
节流:在设定的时间内,记录第一个
函数,并在时间结束后执行此函数。
在抢购按钮、scrollTop监听等事件中会用到,并会使这些函数以设定的时间频率触发。
简单实现:
function throttle (fn, delay = 1000) {
// 记录最后函数触发时间
let last = 0
return function () {
const context = this
const args = arguments
const now = +new Date()
// 当前时间与本次函数触发时间差是否大于时间阙值
if (now - last >= delay) {
last = now
fn.apply(context, args)
}
}
}
优化 debounce throttle
debounce 优化虽然好,但是缺点在于如果你一直在设定时间内触发此函数
,会导致函数一直不执行
,会使用户产生疑惑,
throttle 的缺点在于,如果用户正好在时间阙值内点击按钮,不会触发此次函数,并且时间阙值到了也不会执行。
所以我们可以使用 throttle
优化 debounce
,在一定周期内,多次点击会缓存函数,在时间阙值结束后执行。
function throttle (fn, delay = 100) {
let last = 0
let timer = null
return function () {
const context = this
const args = arguments
const now = +new Date()
if (now - last < delay) {
clearTimeout(timer)
timer = setTimeout(function () {
last = now
fn.apply(context, args)
}, delay)
} else {
last = now
fn.apply(context, args)
}
}
}