【校招VIP】JavaScript-节流函数的实现

08月23日 收藏 0 评论 0 前端开发

【校招VIP】JavaScript-节流函数的实现

转载声明:文章来源:https://blog.csdn.net/qq_42181069/article/details/121934002

1、对节流函数该怎么理解

日常小案例:

老师在上完课后给大家【五分钟】询问大家有没有什么问题要问

但是在【五分钟】之内,不管有多少同学 来问问题,都只会【解答一个问题】

如果在解答一个问题后,5分钟过后还没有同学问问题,那么就下课

所以用三句话理解就是:

当事件触发时,会触发这个事件的响应函数

当事件密集触发时,节流函数会按照一定的频率来执行函数

不管在这个中间有多少次触发这个事件,执行函数的频率总是固定的

2、拙劣的图解

3、 节流的应用场景

监听页面的滚动事件

鼠标的移动事件

用户频繁点击按钮操作

4、节流的简单实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//简单实现
function throttle(fn, interval) {
    //1.记录上一次的开始时间
    let lastTime = 0
  
    //2.事件触发时,真正的执行函数
    const _throttle = function (...args) {
  
        //2.1 获取当前事件触发时的时间
        const nowTime = new Date().getTime()
  
        //2.2 使用当前触发的时间和之前的时间间隔以及上一次开始的时间, 计算出还剩余多长事件需要去触发函数
        const remainTime = interval - (nowTime - lastTime)
        if (remainTime <= 0) {
            //2.3 真正触发函数
            fn.apply(this, args)
            //2.4 保留上次触发的时间
            lastTime = nowTime
        }
    }
    return _throttle
}

5、增加功能-第一次是否立即执行

注意:第一次是会立即执行的,lastTime为0,nowTime是个很大的值,interval - (nowTime - lastTime)一定是负数的

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
//第一次是否立即执行
function throttle(fn, interval, options = {leading: true}) {
    //1.记录上一次的开始时间
    let lastTime = 0
    const {
        leading
    } = options
    //2.事件触发时,真正的执行函数
    const _throttle = function (...args) {
  
        //2.1 获取当前事件触发时的时间
        const nowTime = new Date().getTime()
  
        if (!lastTime && !leading) lastTime = nowTime
        //2.2 使用当前触发的时间和之前的时间间隔以及上一次开始的时间, 计算出还剩余多长事件需要去触发函数
        const remainTime = interval - (nowTime - lastTime)
        if (remainTime <= 0) {
            //2.3 真正触发函数
            fn.apply(this, args)
            //2.4 保留上次触发的时间
            lastTime = nowTime
        }
    }
    return _throttle
}

6、增加功能-最后一次是否执行

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
function throttle(fn, interval, options = {leading: true,trailing: false}) {
    //1.记录上一次的开始时间
    let lastTime = 0
    let timer = null
    const {
        leading,
        trailing
    } = options
    //2.事件触发时,真正的执行函数
    const _throttle = function (...args) {
  
        //2.1 获取当前事件触发时的时间
        const nowTime = new Date().getTime()
  
        if (!lastTime && !leading) lastTime = nowTime
        //2.2 使用当前触发的时间和之前的时间间隔以及上一次开始的时间, 计算出还剩余多长事件需要去触发函数
        const remainTime = interval - (nowTime - lastTime)
        if (remainTime <= 0) {
            if (timer) {
                clearTimeout(timer)
                timer = null
            }
            //2.3 真正触发函数
            fn.apply(this, args)
            //2.4 保留上次触发的时间
            lastTime = nowTime
            return
        }
        //2.3 最后一次是否执行
        if (trailing && !timer) {
            timer = setTimeout(() => {
                timer = null
                lastTime = !leading ? 0 : new Date().getTime()
                fn.apply(this, args)
            }, remainTime)
        }
    }
    return _throttle
}

7、增加功能-函数返回值

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
//函数返回值
function throttle(fn, interval, options = {leading: true,trailing: false}) {
    //1.记录上一次的开始时间
    let lastTime = 0
    let timer = null
    const {
        leading,
        trailing,
        resultCallback
    } = options
    //2.事件触发时,真正的执行函数
    const _throttle = function (...args) {
        return new Promise((resolve, reject) => {
            //2.1 获取当前事件触发时的时间
            const nowTime = new Date().getTime()
  
            if (!lastTime && !leading) lastTime = nowTime
            //2.2 使用当前触发的时间和之前的时间间隔以及上一次开始的时间, 计算出还剩余多长事件需要去触发函数
            const remainTime = interval - (nowTime - lastTime)
            if (remainTime <= 0) {
                if (timer) {
                    clearTimeout(timer)
                    timer = null
                }
                //2.3 真正触发函数
                const result = fn.apply(this, args)
                if (resultCallback) resultCallback(result)
                resolve(result)
                //2.4 保留上次触发的时间
                lastTime = nowTime
                return
            }
            //2.3 最后一次是否执行
            if (trailing && !timer) {
                timer = setTimeout(() => {
                    timer = null
                    lastTime = !leading ? 0 : new Date().getTime()
                    const result = fn.apply(this, args)
                    if (resultCallback) resultCallback(result)
                    resolve(result)
                }, remainTime)
            }
        })
  
    }
    _throttle.cancel = function () {
        if (timer) clearTimeout(timer)
        timer = null
        lastTime = 0
    }
    return _throttle
}

8、代码测试

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
55
56
57
58
59
60
61
62
<!DOCTYPE html>
<html lang="en">
  
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
  
<body>
    <input type="text">
    <button id="cancel">取消</button>
    <script src="./throttle.js"></script>
    <script>
        const inputEl = document.querySelector("input")
        let counter = 0
  
        const inputChange = function (event) {
            console.log(`发送了第${++counter}次网络请求`, this, event)
  
            // 返回值
            return "当地小有名气的可爱鬼"
        }
        //简单版本
        inputEl.oninput = throttle(inputChange, 2000)
  
        // 1、测试是否立即执行
        inputEl.oninput = throttle(inputChange, 2000, { leading: false })
        inputEl.oninput = throttle(inputChange, 2000, { leading: true })
  
        //1.1 测试最后一次是否执行
        inputEl.oninput = throttle(inputChange, 2000, { leading: true , trailing : true })
        inputEl.oninput = throttle(inputChange, 2000, { leading: true, trailing: false })
  
        //2、测试取消功能
        const throttleChange = throttle(inputChange, 2000, { leading: true, trailing: false })
        const cancelBtn = document.querySelector('#cancel')
        cancelBtn.onclick = function () {
            throttleChange.cancel()
        }
  
        // // 3、测试函数带返回值
        const _throttle = throttle(inputChange, 1000, {
            leading: false,
            trailing: true,
            resultCallback: function (res) {
                console.log("resultCallback:", res)
            }
        })
        inputEl.oninput = _throttle
  
        const tempCallback = (...args) => {
            _throttle.apply(inputEl, args).then(res => {
                console.log("Promise:", res)
            })
        }
        inputEl.oninput = tempCallback
    </script>
</body>
  
</html>


C 0条回复 评论

帖子还没人回复快来抢沙发