节流通俗解释:技能cd,最好写成通用的形式,因为不能为了一个功能写一个节流,那一百个功能难道要写100个节流?
应用场景:比如不想用户频繁点击按钮,想在规定时间内只允许点击一次
思路:
接收一个函数和时间,调用传入的fn函数,冷却中=true
设置一个计时器,时间设为传入的时间time,time过后,冷却中=false
// 节流就是「技能冷却中」
const throttle = (fn, time) => {
let 冷却中 = false
return (...args) => {
if (冷却中) return
fn.call(undefined, ...args)
冷却中 = true
setTimeout(() => {
冷却中 = false
}, time)
}
}
// 还有一个版本是在冷却结束时调用 fn
// 简洁版,删掉冷却中变量,直接使用 timer 代替
const throttle = (fn, time) => {
let timer = null
return (...args) => {
if (timer) { return }
fn.call(undefined, ...args)
timer = setTimeout(() => {
timer = null
}, time)
}
}
const f = throttle(()=>{console.log('hi')}, 3000)
f() // 打印hi
f() // 技能冷却中
防抖通俗解释:点击B回城时,被打断,再点B回城,再被打断,再B….,直到回城成功。
一样写成通用的形式
应用场景:调整浏览器窗口大小时 只有规定时间后执行重新定位
思路:
接收fn 和 time
设置计时器,在time时间后执行fn,如果期间被打断
就重置计时器,重新开始计算time时间,time结束后执行fn
循环往复,直至fn被执行
// 防抖就是「回城被打断」
const 回城 = function(){
console.log('回城成功')
}
const debounce = (fn, time) => {
let timer = null
return (...args) => {
if (timer !== null) {
clearTimeout(timer) // 打断回城
}
// 重新回城
timer = setTimeout(() => {
fn.call(undefined, ...args) // 回城后调用 fn
timer = null
}, time)
}
}
const tp = debounce(回城,3000)
tp() //失败
tp() //失败
tp() //失败
tp() //三秒后成功