防抖(debounce)
概念
在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
怎么理解这句话,有网友这样比喻:
LOL英雄有些技能发动前要读条(比如1s),如果这1s内又按下技能键,就要重新读条
实现
function debounce(fn, wait = 1000, immediate) {
let timerId = null
function debounced(...args) {
if (timerId) clearTimeout(timerId)
if (immediate) {
// timerId为空时,立即执行
let isCallNow = !timerId
// 开始延时
timerId = setTimeout(() => {
timerId = null
}, wait)
if (isCallNow) fn.apply(this, args)
} else {
timerId = setTimeout(() => {
fn.apply(this, args)
}, wait)
}
}
return debounced
}
验证:
<script>
const debounceOk = debounce(() => {
handleOk()
}, 1000, true)
function handleOk() {
console.log('ok')
}
</script>
<div>
<button onclick="debounceOk()">确定</button>
</div>
节流(throttle)
概念
规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。 还是以LOL为例: 当前英雄的攻速为1.0, 那1s内就能一次平a。
实现
function throttle(fn, wait = 2000) {
let prev = Date.now()
function throttled(...args) {
let now = Date.now()
if (now - prev > wait) {
fn.apply(this, args)
prev = Date.now()
}
}
return throttled
}
验证:
<script>
const throttleOk = throttle(() => {
handleOk()
}, 1000)
function handleOk() {
console.log('ok', Date.now())
}
</script>
<div>
<button onclick="throttleOk()">确定</button>
</div>