函数防抖:
在一些很常见的应用场景,如有一个按钮,点击按钮发起请求获取数据,在某些场景下用户可能会多次反复点击,这个时候如果不做任何措施,就会同时发起多次相同请求,可能会造成页面以及增加服务器的压力。而防抖就是为了优化这种应用场景,防抖函数一般接收两个参数,分别是要进行处理的事件方法和要进行防抖延迟的时间(暂且规定为delay),用户触发一次事件后不会立即执行,而是延迟delay ms后才会执行事件方法,而如果在delay ms期间内用户再次触发该事件,则会刷新倒计时,直到下一次delay截止才会触发事件。 大致的效果就是:当用户多次频繁触发防抖处理过的事件,浏览器总是只执行一次。这样便可以大大优化请求效率,减轻服务器的负担。
尝试尽可能多的方式来实现函数防抖:
No.1 定时器版,首次触发延迟执行,执行最后一次触发
我的思路是是用定时器函数,当初次触发时设置定时器,若time ms内再次触发则重置定时器,这样的效果便是最后一次触发总会执行,但第一次触发会延迟。
// 初次延迟,末次执行
function debounce (func, time) {
let timer = null
return function() {
timer && clearTimeout(timer)
timer = setTimeout(() => {
func.call(this, ...arguments)
timer = null
}, time);
}
}
No.2 时间戳版,首次触发立即执行,末次触发不执行
上面的定时器版虽然可以执行末次触发,但是首次触发延迟非常不符合操作逻辑,会给人迟钝但感觉,所以我用时间戳实现了一个新的防抖函数。
// 初次立即执行,末次不执行
function debounce (func, time) {
let old = 0
return function() {
const now = new Date().getTime()
if(now - old >= time) {
func.call(this, ...arguments)
}
old = now
}
}
No.3 定时器与时间戳结合版,完美方案,初次执行,末次执行
定时器和时间戳版都有各自的优缺点,那么我们可以将它们结合起来:
// 初次立即执行,末次执行
function debounce (func, time) {
let old = 0, timer = null
return function() {
let now = new Date().getTime()
timer && clearTimeout(timer)
if(now - old >= time) {
func.call(this, ...arguments)
} else {
timer = setTimeout(() => {
func.call(this, ...arguments)
timer = null
}, time);
}
old = now
}
}
函数节流:
函数节流是密集触发事件机制时,用某种方法让函数每隔一段时间才执行一次,如浏览器监听下滑事件时,可以用函数节流让下滑事件每隔规定时间才执行一次,节约性能消耗,优化页面使用体验。有点类似将一直打开的水龙头变成每隔一段时间才开一次。
function throttle(func, time) {
let old = 0
return function() {
const now = new Date().getTime()
if(now - old >= time ) {
func(...arguments)
old = now
}
}
}