节流和防抖
申明,本来想找一个大佬的文章,以前还是看的他将的故事,才懂的,现在找不到了,如果有看到的同学说一下,我标注一下链接
假设在一个公交车站,如果把执行一次目标函数相当于发一次车,那么发车的间隔和怎么判断发车就很值得注意了
情况一:发车频繁 (节流)
节流:
连续触发事件但是在 n 秒中只执行一次函数
具体:
由于各个时间段公交车站都会来人,司机无法确定时间,有人来了就要发车(假定这样的话),
公交车站的车除非有无穷多,不然根本完成任务(极端情况,直接崩溃)。于是,有人想到了解决办法
办法:
约定一个时间长度,没一个时间长度,发一次车,人来再多也要等到时间才发车。
节流代码:
//版本1 版本没有那种更好,实现方式稍微不同
function throttle(callback, delay) {
let timer = null
return function() {
const thisContext = this
const thisArguments = Array.from(arguments)
if(!timer) {
timer = setTimeout(()=>{
callback.apply(thisContext, thisArguments)
timer = null
}, delay)
}
}
}
//版本2 时间戳
function throttleTimestamp(callback, delay) {
let startTime = +(new Date())
return function() {
const thisContext = this
//事实证明 apply也可以传入伪数组,比如arguments
const thisArguments = Array.from(arguments)
const currentTime = +(new Date())
if(currentTime - startTime >= delay) {
callback.apply(thisContext, thisArguments)
startTime = +(new Date())
}
}
}
情况二:汽车站的最后一趟
防抖:
触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
具体:
在出现了情况一的前提下,出现了一点点小问题,如果某天时间快结束了,如果时间不够一个时间长度,那这些乘客岂不是无法乘车?
当然要满足客户啦!但是 只剩最后一辆车了,当然希望尽可能的装下更多人, 那要怎么等人呢?
办法:
约定一个时间长度,过位这个时间长度就发车,但是如果又有人来,重新计算时间,再等一个时间长度,依次往复。
节流代码:
function debounce(callback, delay) {
let timer = null
return function() {
if(timer) clearTimeout(timer)
const thisContext = this
const thisArguments = Array.from(arguments)
timer = setTimeout(()=>{
callback.apply(thisContext, thisArguments)
timer = null
}, delay)
}
}
综合上面的情况,选择两种融合
function mergeThrottleDebounce(callback, delay) {
let startTime = +(new Date())
let timer = null
return function() {
const thisContext = this
//事实证明 apply也可以传入伪数组,比如arguments
const thisArguments = Array.from(arguments)
const currentTime = +(new Date())
if(currentTime - startTime >= delay) { //超时发车
callback.apply(thisContext, thisArguments)
startTime = +(new Date())
}else { // 未到时间重新发车计时
if(timer) clearTimeout(timer)
timer = setTimeout(() => {
callback.apply(thisContext, thisArguments)
startTime = +(new Date())
}, delay)
}
}
}