防抖
-
持续触发事件时。一定时间没有继续触发,事件处理函数才会执行一次
-
input (巨量引擎)
如果有人进电梯,那电梯将在10秒钟后出发,这时如果又有人进电梯了,我们又得等10秒再出发
- 通过闭包维护一个变量,此变量代表是否已经开始计时,如果已经开始计时则清空之前的计时器,重新开始计时
场景
-
表单提交:当用户停止输入一段时间后才会发送请求
-
搜索框自动补全:当用户在搜索框中输入关键词时,实时查询后台数据并展示自动补全列表
-
窗口大小改变:当窗口大小改变时,需要重新计算页面布局
实现
function debounce(fn, time) {
let timer = null
return function () {
let context = this
let args = arguments
if (timer) {
clearTimeout(timer)
timer = null
}
timer = setTimeout(function () {
fn.apply(context, args)
}, time)
}
}
window.onscroll = debounce(function () {
console.log('触发' + new Date().getTime())
}, 1000)
节流
- 持续触发事件时,保证一定时间段内只调用一次事件处理函数
-
游戏内的技能冷却,无论你按多少次,技能只能在冷却好了之后才能再次触发
-
通过闭包维护一个变量,此变量代表是否允许执行函数,如果允许则执行函数并且把该变量修改为不允许,并使用定时器在规定时间后恢复该变量
场景
-
页面滚动
- resize scroll
-
频繁点击按钮:确保只有在一定时间内才能触发一次事件
-
实时网络传输:控制发送数据的频率
实现
// 节流
// 时间戳写法
// 第一次执行时 last 为 0 ,所以是立即执行
function throttle(fn, interval) {
let last = 0
return function () {
let now = Date.now()
if (now - last >= interval) {
last = now
fn.apply(this, arguments)
}
}
}
function handle() {
console.log(Math.random())
}
const throttleHandle = throttle(handle, 1000)
throttleHandle()
// 第一次不立即执行,但是最后一次会有延迟
function throttle2(fn, interval) {
let timer = null
return function () {
let context = this
let args = arguments
if (!timer) {
timer = setTimeout(() => {
fn.apply(context, args)
}, interval)
}
}
}
// 结合版本
function throttle3(fn, delay) {
let timer = null
let startTime = Date.now()
return function () {
let curTime = Date.now()
let remainning = delay - (curTime - startTime)
let context = this
let args = arguments
clearTimeout(timer)
if (remainning <= 0) {
fn.apply(context, args)
startTime = Date.now()
} else {
timer = setTimeout(fn, remainning)
}
}
}