• javascript中的函数节流和函数去抖


    带着问题去尝试

    首先我们要知道为什么要用到函数节流和函数去抖?我们带着以下的疑问来进行分析!

    1.比如搜索框,你会用到什么事件(change、blur、keyup等)?去做什么效果?
    2.再比如scroll滚动事件,怎么去触发?是滚一段距离触发一次?还是滚一圈触发一次?还是滚一次触发一次?
    3.还包括mouseover事件是怎么触发呢?
    ......

    场景实例

    函数节流和去抖的出现场景,一般都伴随着客户端 DOM 的事件监听。举个例子,实现一个原生的拖拽功能(不能用 H5 Drag&Drop API),需要一路监听 mousemove 事件,在回调中获取元素当前位置,然后重置 dom 的位置(样式改变)。如果我们不加以控制,每移动一定像素而触发的回调数量是会非常惊人的,回调中又伴随着 DOM 操作,继而引发浏览器的重排与重绘,性能差的浏览器可能就会直接假死,这样的用户体验是非常糟糕的。我们需要做的是降低触发回调的频率,比如让它 500ms 触发一次,或者 200ms,甚至 100ms,这个阈值不能太大,太大了拖拽就会失真,也不能太小,太小了低版本浏览器可能就会假死,这样的解决方案就是函数节流,英文名字叫「throttle」。函数节流的核心是,让一个函数不要执行得太频繁,减少一些过快的调用来节流。

    说完函数节流,再看它的好基友函数去抖(debounce)。思考这样一个场景,对于浏览器窗口,每做一次 resize 操作,发送一个请求,很显然,我们需要监听 resize 事件,但是和 mousemove 一样,每缩小(或者放大)一次浏览器,实际上会触发 N 多次的 resize 事件,用节流?节流只能保证定时触发,我们一次就好,这就要用去抖。简单的说,函数去抖就是对于一定时间段的连续的函数调用,只让其执行一次。

    实例了解

    下面就让我们来了解throttle(节流) 和 debounce(去抖)

    1.throttle节流,scroll和mouseover亦或者其他方式,每次移动都会触发代码效果,但是这些效果太密集了,占用了系统资源,计算机的计算能力是有限的,我们写的代码应该尽可能的优雅。
    2.debounce去抖,本意是从按键去抖过来的,让我们的用户正确的操作之后才去执行代码,且只会执行一次,比如当我们做文本输入的时候,如果用keyup我们不是去节流,而是去判断用户停止了输入。
    3.节流保证在一定时间内,只能触发一次。如果我们只要触发一次,这就是去抖。代码上来看差距不是很大。

    直接试一下:

    //先来个有问题的代码
    window.onscroll=function(){
        console.log(new Date());
    }

    控制台会打印:

    VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中国标准时间)
    VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中国标准时间)
    VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中国标准时间)
    VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中国标准时间)
    VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中国标准时间)
    VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中国标准时间)
    ...

    控制台会一直这样输入,那问题来了,这获取并不是我们想要的,我们并不想让他一直触发下去。

    我们要解决这些问题,所以直接看代码:

    //我们先来个节流,每秒输出一次
    window.onscroll=function(){
        if(window.onScrollTag == undefined){
            window.onScrollTag=true;
            console.log(new Date());
            setTimeout(function(){
                window.onScrollTag=undefined;
            },1000);
        }
    }//先触发
    window.onscroll=function(){
        if(window.onScrollTag == undefined){
            window.onScrollTag=setTimeout(function(){
                window.onScrollTag=undefined;
                 console.log(new Date());
            },1000);
           
        }
    }//后触发
    //从上面的代码可以看出来,我们在一个事件执行的时候就把标记改成不可用。一秒后才可以再次触发操作。
    //我们在尝试一下去抖
    window.onscroll=function(){
        if(window.onScrollTag != undefined){
            clearTimeout(window.onScrollTag);
        }
        window.onScrollTag=setTimeout(function(){
             console.log(new Date());
        },1000);
    }//消抖,消除抖动,感觉这个更好听
    //节流
    funtion throttle(func, wait) {  
        var lastTime = 0,
            timeout;  
        return funtion() {    
            var context = this,
                args = arguments,
                delay = wait || 100,
                now = new Date().getTime();    
            if (now - lastTime <= delay) {      
                return;    
            }    
            lastTime = now;
            clearTimeout(timeout);  
            timeout = setTimeout(function() {
                timeout = null;
                func.apply(context, args);
            }, delay)  
        }
    }
    // 去抖
    function debounce(func, wait) {
        var timeout;
        return function() {
            var context = this,
                args = arguments,
                delay = wait || 250;
            clearTimeout(timeout);
            timeout = setTimeout(function() {
                timeout = null;
                func.apply(context, args);
            }, delay);
        };
    }

    throttle 应用场景

    函数节流有哪些应用场景?哪些时候我们需要间隔一定时间触发回调来控制函数调用频率?

    • DOM 元素的拖拽功能实现(mousemove)
    • 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)
    • 计算鼠标移动的距离(mousemove)
    • Canvas 模拟画板功能(mousemove)
    • 搜索联想(keyup)
    • 监听滚动事件判断是否到页面底部自动加载更多:给 scroll 加了 debounce 后,只有用户停止滚动后,才会判断是否到了页面底部;如果是 throttle 的话,只要页面滚动就会间隔一段时间判断一次

    debounce 应用场景

    函数去抖有哪些应用场景?哪些时候对于连续的事件响应我们只需要执行一次回调?

    • 每次 resize/scroll 触发统计事件
    • 文本输入的验证(连续输入文字后发送 AJAX 请求进行验证,验证一次就好)

    小结

    函数节流和函数去抖的核心其实就是限制某一个方法被频繁触发,而一个方法之所以会被频繁触发,大多数情况下是因为 DOM 事件的监听回调,而这也是函数节流以及去抖多数情况下的应用场景

    如果大家感兴趣,可以参考下:http://underscorejs.org/ 

  • 相关阅读:
    monitor system
    monitor disk
    manage account
    windows
    backup daily
    shell 脚本编程概述
    OGNL表达式
    Struts2各个功能详解(2)-输入校验和拦截器
    struts2各个功能详解(1)----参数自动封装和类型自动转换
    Struts2源码解析2
  • 原文地址:https://www.cnblogs.com/shoestrong/p/6538783.html
Copyright © 2020-2023  润新知