防抖和节流

防抖和节流的实现

防抖

对于这个高频的操作来说,我们只希望识别一次点击,可以人为是第一次或最后一次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* handle最终需要执行的事件监听
* wait 时间多久后执行
* immediate true第一次执行, false只执行最后一次
*/
function debounce (handle, wait, immediate) {
// 参数类型判断
if (typeof handle !== 'function') throw new Error('这不是一个函数')
if (typeof wait === 'undefined') wait = 300
if (typeof wait === 'boolean') {
immediate = wait
wait = 300
}
let timer = null

//管理handle的执行次数
// 想要执行最后一次,意味无论我们当前点击了多少次,前面的N-1次都无用
return function proxy (...args) {
let self = this,
init = immediate && !timer // immediate为true第一次执行,同时timer不存在,代表没有执行过
clearTimeout(timer)
timer = setTimeout(() => {
timer = null
// 传参
!immediate ? handle.call(self, ...args) : null
}, wait)
// 执行第一次
init ? handle.call(self, ...args) : null
}
}

节流

对于高频操作,我们可以设置频率,让本来会执行很多次的事件触发,按照我们定义的频率减少触发的次数

  1. 假设当前在5s的时间点上执行了一次proxy,可以用这个时间减去上次执行的时间(0),此时就会有一个时间差
  2. 定义一个wait,比如定义wait为500
  3. wait - (now - previous) 定义的时间-(当前时间-上一次执行的时间)
  4. 如果计算结果大于0,当前的操作是一个高频操作触发,不要去执行handle.如果小于等于0,当前不是一个高频操作,可以执行handle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
function scrollFn () {
console.log('滚动')
}
/**
* handle最终需要执行的事件监听
* wait 时间多久后执行
*/
function throttle (handle, wait) {
if (typeof handle !== 'function') throw new Error('这不是一个函数')
if (typeof wait === 'undefined') wait = 400

// 记录上一次执行的时间
let previos = 0
// 管理定时器
let timer = null

return function proxy (...args) {
// 记录当前执行的时间
let now = new Date()
let self = this
let interval = wait - (now - previos)

if (interval <= 0) {
// 非高频次操作
// 只是将系统中的定时器清除了,但timer中的值还在,timer需要null
clearInterval(timer)
timer = null
handle.call(self, ...args)
previos = new Date()
} else if (!timer) {
// 当前系统中有一个定时器了,就意味着我们不需要再开启定时器
// 这次的操作发生在了定义的频次时间范围内,就不应该执行handle
// 自定义一个定时器,让handle在interval后执行
timer = setTimeout(() => {
// 只是将系统中的定时器清除了,但timer中的值还在,timer需要null
clearInterval(timer)
timer = null
handle.call(self, ...args)
previos = new Date()
}, interval)
}
}
}

// window.onscroll = scrollFn
window.onscroll = myThrottle(scrollFn, 3000)