持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情
有时候当我们在面试的时候,面试馆会问:“你知道防抖吗?”在刚开始学习的时候,一脸懵逼防抖时候什么鬼?后来进过面试和自己的一一些工作经验发现,防抖和节流是非常常见的。
防抖
首先有这样一个需求,在输入框输入内容结束后向后端发送数据,当我们不停的输入时,发现会一直往后端发送数据,此时太消耗性能,于是产生了防抖函数。
在函数触发n秒内,函数再次被触发,那么会重新计算函数执行时间 场景有:input输入框提交数据,window窗口size大小改变
非立即执行版
let inputBtn = document.getElementById('btn')
inputBtn.addEventListener("keyup",(e) => {
input(e.target.value)
})
function submit(val) {
console.log('给后端传送数据',val)
}
function debounce(fn,delay) {
let timer = null
return function() {
if(timer) clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this,arguments)
},delay)
}
}
let input = debounce(submit,3000)
立即执行版
上一个版本是当第一次输入的时候就会产生延时的效果,如果在第一次执行完后延迟了3s发送数据,此时网络又比较慢,那么等数据响应完后中间时间差隔太大,很有可可能会造成用户的流失,接下来改进一下,在用户输入完后会立马发送数据。
触发事件后函数会
立即执行一次
,然后 n 秒内再次触发事件不继续执行函数的效果
function debounce(fn,delay) {
let timer = null
return function() {
// 立即执行的开关
let firstSubmit = !timer
if(timer) clearTimeout(timer)
if(firstSubmit) {
fn.apply(this,arguments)
}
timer = setTimeout(() => {
timer = null
},delay)
}
}
节流
在n秒内函数只执行一次 场景:
- 鼠标不断点击触发,mousedown(单位时间内只触发一次)
- 监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断
定时器版本
function throttle(fn,delay){
let timer
return function() {
if (timer) {
return
}
timer = setTimeout(() => {
fn.apply(this,arguments)
timer = null
},delay)
}
}
时间戳版本
function throttle(fn,delay) {
let pre = 0
return function () {
let now = new Date().now()
if(now - pre > delay) {
fn.apply(this,arguments)
pre = now
}
}
}