防抖debounce
连续的多次动作内,只执行最后一次动作
?? 设想下面场景:
-
有一个提交按钮,每次点击提交之后,就会向后台发起ajax请求 -
这样设计会有问题:用户在一定时间内多次点击提交,按钮就会像多次向后台发送请求!! -
这时候,防抖就非常有用:用户在一定时间内无论多点击多少次提交,按钮只会提交一次
🔑 防抖有两种执行模式:
-
在一定动作内执行最后一次动作 -
在一定动作内只执行首次动作
流程图地址:https://processon.com/diagraming/6162fee37d9c0866512e839d
function debounce(func, wait = 300, immediately) {
let timer, result
let debounce = function (...args) {
if (timer) clearTimeout(timer)
if (immediately) {
let callNow = !timer
timer = setTimeout(() => {
timer = null
}, wait)
if (callNow) result = func.apply(this, args)
} else {
new Promise((resolve, reject) => {
timer = setTimeout(() => {
resolve(func.apply(this, args))
timer = null
}, wait)
})
}
return result
}
debounce.cancel = function () {
clearTimeout(timer)
timer = null
}
return debounce
}
🏰 案例
应用场景:
- scroll事件滚动触发
- 搜索框输入查询
- 表单验证
- 按钮提交事件
- 浏览器窗口缩放,resize事件
-节流throttle
连续的多次动作内,在固定周期内,一个周期执行一次动作
?? 还是举一个例子:
- 我现在有一个图片预览网站,里面有很多图片,需求是实现图片懒加载的监听
- 这里的问题是:每次拉动滚动条,就会触发事件去对比图片是否到达可视区域,触发非常频繁
- 这时候,节流就非常有用:在用户拉动滚动条的时候,我只在500ms这个周期内触发事件
🔑 节流有两种执行模式:
-
刚触发事件时会执行一次,后续周期会触发事件,最后一次事件不触发(顾头不顾尾) -
刚触发事件时不执行,后续周期会触发事件,最后一次事件会触发(顾尾不顾头) -
刚触发事件时会执行一次,后续周期会触发事件,最后一次事件会触发(顾头顾尾)
流程图地址:https://processon.com/diagraming/6163d0bae0b34d7c7da62cba
function throttle(func, wait, opt = {leading: true, trailing: true}) {
let timer,
old = 0
return function (...args) {
let now = new Date().valueOf()
let later = () => {
old = new Date().valueOf()
func.apply(this, args)
timer = null
}
if(opt.leading === false) old = now
if (now - old > wait) {
if (timer) {
clearTimeout(timer)
timer = null
}
func.apply(this, args)
old = now
} else if (!timer && opt.trailing !== false) {
timer = setTimeout(later, wait)
}
}
}
🏰 案例
- DOM元素拖拽
- 飞机每隔一段事件射击导弹
- 监听scroll滚动事件
- 计算鼠标移动的距离
|