节流

34 阅读1分钟

节流:间隔一段时间执行一次回调 节流应用场景有: 滚动加载,加载更多或滚到底部监听 谷歌搜索框,搜索联想功能 高频点击提交,表单重复提交

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>节流</title>
</head>
<style>
    body{
        height: 1000px;
    }
</style>
<body>

    <script>
        /**
         * 1、假设当前在5ms的时间点上执行了一次proxy,我们就可以用这个时间减去上次执行的时间,此时就会有一个时间差
         * 2、前置条件:我们自己定义了一个wait,
         * 3、wait-(now-previous)
         * 4、此时如果上述的计算结果如果是大于0的,就意味着当前次的操作是一个高频次触发,我们想办法让它不要去执行handle,如果这个结果小于等于0,浙江意味着当前次不是一个高频次触发,那么我们就可以直接执行handle
         * 
        */
        // 节流:自定义一段时间内让事件进行触发
        function myThrottle(handle, wait){
            if(typeof handle !== 'function') throw new Error('handle must be an function')
            if (typeof wait === 'undefined') wait = 300
            let previous = 0 // 定义变量记录上一次执行时的时间
            let self = this
            let timer = null
            return function proxy(...args){
                let now = new Date()
                let interval = wait - (now - previous)
                if(interval <= 0 ){
                    handle.call(self, ...args)
                    previous = new Date()
                    clearTimeout(timer)
                    timer = null
                } else if(!timer){
                    // 当我们发现当前系统中有一个定时器了,就意味着我们不需要再开启定时器
                    // 此时说明这次的操作发生在了我们定义的频次的时间范围内,那就不应该执行handle
                    // /这个时候就可以自己定义一个定时器,让handle在interval之后去执行
                    timer = setTimeout(()=>{
                        clearTimeout(timer)
                        timer = null
                        handle.call(self, ...args)
                        previous = new Date()
                    }, interval)
                }
            }
        }
        // 定义滚动事件
        function scrollFn(){
            console.log('滚动了')
        }
        // window.onscroll = scrollFn
        window.onscroll = myThrottle(scrollFn, 5000)
    </script>
</body>
</html>