throttle【截流】
描述
截流函数
# 1.示例
import { throttle } from 'sf-utils2'
const bodyDom = document.querySelector('body')
const scrollFn = e => {
console.log('滚动了', e.target)
}
// 在计时结束之后执行
const throttleScroll = throttle(scrollFn, 20) // 每隔20ms只值执行一次
bodyDom.addEventListener('scroll', throttleScroll, false) // 开始监听
bodyDom.removeEventListener('scroll', throttleScroll, false) // 卸载监听
// 在计时结束之前执行
bodyDom.addEventListener(
'resize',
throttle(scrollFn, 20, {
leading: true,
trailing: false
})
)
// 在计时结束之后执行
bodyDom.addEventListener(
'resize',
throttle(scrollFn, 20, {
leading: false,
trailing: true
})
)
let func = throttle(function (msg) {
console.log(msg)
}, 300)
func('执行一次')
func.cancel()
func('取消后中断计时,再次调用会马上执行')
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
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
# 2.入参说明
| 参数 | 说明 | 类型 | 是否必填 | 默认值 |
|---|---|---|---|---|
| fn | 回调函数 | Function | 是 | |
| wait | 周期时间内执行一次,单位毫秒 | Number | 否 | 默认 20 毫秒 |
| options | 选项 详情见下 👇 | Object | 否 |
# options 对象
| 参数 | 说明 | 类型 | 是否必填 | 默认值 |
|---|---|---|---|---|
| leading | 是否在之前执行 | Boolean | 否 | true |
| trailing | 是否在之后执行 | Boolean | 否 | false |
# 3.源码
/**
* 节流函数;当被调用 n 毫秒后才会执行,如果在这时间内又被调用则至少每隔 n 秒毫秒调用一次该函数
* 默认在定时器之前执行
*
* @param {Function} callback 回调
* @param {Number} wait 多少秒毫 默认值 20 毫秒
* @param {Object} options 参数{leading: 是否在之前执行, trailing: 是否在之后执行}
* @return {Function}
*/
function throttle(callback, wait = 20, options = { leading: true, trailing: false }) {
let args, context
let opts = options || {}
let runFlag = false
let isDestroy = false
let timeout = 0
let optLeading = 'leading' in opts ? opts.leading : true
let optTrailing = 'trailing' in opts ? opts.trailing : false
let runFn = function () {
if (!isDestroy) {
runFlag = true
callback.apply(context, args)
timeout = setTimeout(endFn, wait)
}
}
let endFn = function () {
timeout = 0
if (!isDestroy && !runFlag && optTrailing === true) {
runFn()
}
}
let cancelFn = function () {
let rest = timeout !== 0
clearTimeout(timeout)
args = null
context = null
runFlag = false
timeout = 0
return rest
}
let throttled = function () {
args = arguments
context = this
runFlag = false
if (timeout === 0) {
if (optLeading === true) {
runFn()
} else if (optTrailing === true) {
timeout = setTimeout(endFn, wait)
}
}
}
throttled.cancel = cancelFn
return throttled
}
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
47
48
49
50
51
52
53
54
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
47
48
49
50
51
52
53
54
上次更新: 2023/06/24, 19:35:48