函数防抖和节流
2020-07-02 本文已影响0人
fanison
防抖
防抖(debounce):
- 如果下达命令后,在t毫秒内再次下达该命令,则取消刚刚下达的命令,只执行新命令
- 最终效果: 对于连续动作(动作间的时间间隔小于t),以最后一次为准
思路:每次触发事件时都取消之前的延时调用方法
function debounce(fn, delay) {
let timer = null // 创建一个标记用来存放定时器的返回值
return function() {
// 每当用户输入的时候把前一个 setTimeout clear 掉
if(timer) { clearTimeout(timer) }
// 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
timer = setTimeout(() => fn.apply(this, arguments), delay)
}
}
const debounced = debounce(()=>console.log('hi'))
debounced()
debounced()
函数防抖的应用场景
连续的事件,只需触发一次回调的场景有:
- 搜索框搜索输入。只需用户最后一次输入完,再发送请求
- 手机号、邮箱验证输入检测
- 窗口大小Resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。
节流
节流(throttle):
- 从上一次命令结束开始的一定时间范围t内,如果多次连续下达命令,则只执行当前时间段t内第一次命令。
- 最终效果:对于连续动作,会过滤出部分动作,让这些过滤后的动作之间的执行间隔大于等于t
函数节流的时间戳版
原理:通过比对上一次执行时间与本次执行时间的时间差与间隔时间的大小,来判断是否执行函数。若时间差大于间隔时间,则立刻执行一次函数。并更新上一次执行时间。
function throttle(fn, delay) {
let lastTime = null
let nowTime = null
return function() {
nowTime = Date.now()
if(!lastTime || nowTime - lastTime > delay) {
fn()
lastTime = nowTime
}
}
}
思路:每次触发事件时都判断当前是否有等待执行的延时函数
function throttle(fn,delay){
let canUse = true //通过闭包保存一个标记
return function(){
if(canUse){ // 在函数开头判断标记是否为true
fn.apply(this,arguments)
canUse = false
setTimeout(()=>canUse = true,delay) //在setTimeout执行完毕后把标记设置为true表示可以执行下一次循环了。
}
}
}
const throttled = throttle(()=>console.log('hi'),1000)
throttled()
throttled()
函数节流的应用场景
间隔一段时间执行一次回调的场景有:
- 滚动加载,加载更多或滚到底部监听
- 谷歌搜索框,搜索联想功能
- 高频点击提交,表单重复提交