函数防抖(debounce)
在事件被触发n秒后再执行回调,如果再这n秒内又被触发,则重新计算
看一个例子:
没有防抖的input: <Input id="unDebounce">
防抖后的input <input>
节流后的input <input>
// 模拟一段ajax请求
function ajax(content) {
console.log('ajax request' + content);
}
let inputa = document.getElementById('unDebounce')
inputa.addEventListener('keyup', function (e) {
ajax(e.target.value)
})
看下运行效果: p1-jj.byteimg.com/tos-cn-i-t2… 可以看到,我们只要按下键盘,就会触发这次ajax请求,不仅仅从资源上来说是很浪费的行为,而且实际应用中,用户也是输出完整的字符后,才会请求,下面我们优化一下
// 防抖——触发高频事件后 n 秒后函数只会执行一次,如果 n 秒内高频事件再 次被触发,则重新计算时间;
function debounce(fn) {
let timeout = null
// 创建一个标记用来存放定时器的返回值
return function () {
clearTimeout(timeout)
// 每当用户输入的时候把前一个 setTimeout clear 掉
timeout = setTimeout(() => {
// 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
fn.apply(this, arguments)
}, 500)
}
}
function sayHi(n) {
console.log('防抖成功')
}
var inp = document.getElementById('debounce')
inp.addEventListener('input', debounce(sayHi)) // 防抖
函数节流(throttle)
规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效
function throttle(fn) {
let canRun = true
// 通过闭包保存一个标记
return function () {
if (!canRun) return
// 在函数开头判断标记是否为 true,不为 true 则 return
canRun = false // 立即设置为 false
setTimeout(() => {
// 将外部传入的函数的执行放在 setTimeout 中
fn.apply(this, arguments)
// 最后在 setTimeout 执行完毕后再把标记设置为 true(关键) 表 示可以执行下一次循环了。当定时器没有执行的时候标记永远是 false,在开头被 return 掉
canRun = true
}, 10000)
}
}
function sayHi(e) {
console.log('节流!!!!~~~')
}
// window.addEventListener('resize', throttle(sayHi))
document.getElementById('debounce').addEventListener('input', sayHi)