首页 > 代码库 > 函数节流

函数节流

1. 函数节流:

  • 由于dom操作极其昂贵,所以尝试过多的dom操作有可能会将浏览器搞崩溃,比如onresize、onscroll这类事件操作;
  • 为了解决这个问题,引出函数节流的概念(某些代码不可以在没有间断的情况下连续重复执行);
  • 方案:第一次调用函数创建一个定时器,在指定时间之后执行代码;在第二次调用时,清除掉前一次的定时器并重新设置一个;
  • 这种方案下,如果第一个定时器已经执行,这个操作就没意义;如果第一个没执行,则将其替换为新的定时器;目的是只有在执行函数的请求停止一段时间后才执行;
  • 适用于代码是周期执行的,但是你不能控制请求执行的速率;
  • 函数节流让一个函数只有在你不断触发后停下来歇会才开始执行,中间你操作得太快它直接无视。
    // 函数节流
    function throttle(method, context) {
        clearTimeout(method.tid);  // mthod是真实要执行的函数,context是执行的作用域(默认window)
        method.tid = setTimeout(function() {
            method.call(context)   // 确保方法在适当的环境中执行
        }, 100);
    }
    
    // onscroll时函数节流
    function scrollFun() {
        var marginBot = 0;
        if (document.documentElement) {
            marginBot = document.documentElement.scrollHeight - (document.documentElement.scrollTop+document.body.scrollTop) - document.documentElement.clientHeight;
        } else {
            marginBot = document.body.scrollHeight - document.body.scrollTop - document.body.clientHeight;
        }
        if(marginBot <= 0) {
            // 滚动到底部加载数据操作
        }
    }
    window.onscroll = function() {
        throttle(scrollFun);
    }

     

2. 函数防抖

  • 如果我们不希望每次都是要事件结束后等待延迟时间后执行回调;

  • 我们可以先给定一个时间段duration,过了这个时间段以后我们执行相应的操作;如果没有过这个时间段,那么就按照函数节流的思路,开关定时器就ok。
    function debounce(method, delay, duration){
        var timer = null, stime = new Date();          // 记录下开始执行函数的时间
        return function() {
            var context = this, args = arguments,
            ctime = new Date();   // 记录下当前时间
            
            clearTimeout(timer);     // 函数节流里的思路
    
            // 记录下的两个时间相减再与duration进行比较
            if (ctime - stime >= duration) {
                method.apply(context, args);
                stime = ctime;
            } else {  
                timer = setTimeout(function(){
                    method.apply(context, args);
                }, delay);
            }
        }
    }
    
    window.onresize = debounce(method, 50, 100);
    // 50ms的间隔内连续触发的调用,后一个调用会把前一个调用的等待处理掉,但每隔100ms至少执行一次

     

3. 滚动实例区分下:

    normal:滚动会立即触发事件执行;

    throttle: 延迟100ms直到100ms以内没有事件触发之后执行,这样如果一直在操作,有可能一直不会触发事件发生;

    debounce:50ms的间隔内连续触发的调用,后一个调用会把前一个调用的等待处理掉,但每隔100ms至少执行一次。

函数节流