zoukankan      html  css  js  c++  java
  • JS性能优化 -- 函数节流

    一、函数节流的概念、主要用途及意义

    概念:函数节流是通过一个定时器,阻断连续重复的函数调用,从而一定程度上优化性能。

    用途:主要用于用户界面调用的函数,如:resize、mousemove、keyup事件的监听函数。
    这类监听函数的主要特征:
    1、短时间内连续多次重复触发;
    2、大量的DOM操作。

    意义:在用户察觉范围外,降低函数调用的频率,从而提升性能

    二、函数节流的原理

    某些代码不可以在没有间断的情况连续重复执行。第一次调用函数,创建一个定时器,在指定的时间间隔之后运行代码。当第二次调用该函数时,它会清除前一次的定时器并设置另一个。如果前一个定时器已经执行过了,这个操作就没有任何意义。然而,如果前一个定时器尚未执行,其实就是将其替换为一个新的定时器。目的是只有在执行函数的请求停止了一段时间之后才执行。

    三、具体用法

    例如:
    1、使用onresize 事件处理程序的时候容易发生,当调整浏览器大小的时候,该事件会连续触发。在onresize 事件处理程序内部如果尝试进行DOM 操作,其高频率的更改可能会让浏览器崩溃。
    2、我们常见的一个搜索的功能,我们一般是绑定keyup事件,每按下一次键盘就搜索一次。但是我们的目的主要是每输入一些内容搜索一次而已。

    为了解决这些问题,就可以使用定时器对函数进行节流。

    基本模式

    var processor = {
       timeoutId: null,
         //实际进行处理的方法
       performProcessing: function(){
         //实际执行的代码
       },
      //初始处理调用的方法
      process: function(){
        clearTimeout(this.timeoutId);
        var _this = this;
        this.timeoutId = setTimeout(function(){
          _this.performProcessing();
        }, 100);
      }
    };
    //尝试开始执行
    processor.process();

    下面以keyup为例

    1、不使用函数节流的情况

    <input id="search" type="text" name="search">
    
    function queryData(text){
        console.log("搜索:" + text);
      }
    var input = document.getElementById("search");
      input.addEventListener("keyup", function(event){ queryData(this.value);
    });

    结果如图:

    这里写图片描述

    2、使用基本函数节流的情况

    <input id="search" type="text" name="search">
    
    function queryData(text){
      console.log("搜索:" + text);
    }
    var input = document.getElementById("search");
    input.addEventListener("keyup", function(event){
      throttle(queryData, null, 500, this.value);
      // queryData(this.value);
    });
    function throttle(fn,context,delay,text){
      clearTimeout(fn.timeoutId);
      fn.timeoutId = setTimeout(function(){
      fn.call(context,text);
      },delay);
    }

    结果如图:

    这里写图片描述

    实际上,我们更希望的是,当达到某个时间值时,一定要执行一次这个搜索函数。所以,就有了函数节流的改进模式。

    3、函数节流增强版

    <input id="search" type="text" name="search">
    
    function queryData(text){
      console.log("搜索:" + text);
    }
    var input = document.getElementById("search");
    input.addEventListener("keyup", function(event){
      throttle(queryData, null, 500, this.value,1000);
      // throttle(queryData, null, 500, this.value);
      // queryData(this.value);
    });
    
    function throttle(fn,context,delay,text,mustApplyTime){
      clearTimeout(fn.timer);
      fn._cur=Date.now();  //记录当前时间
    
      if(!fn._start){      //若该函数是第一次调用,则直接设置_start,即开始时间,为_cur,即此刻的时间
        fn._start=fn._cur;
      }
      if(fn._cur-fn._start>mustApplyTime){ 
      //当前时间与上一次函数被执行的时间作差,与mustApplyTime比较,若大于,则必须执行一次函数,若小于,则重新设置计时器
         fn.call(context,text);
         fn._start=fn._cur;
      }else{
        fn.timer=setTimeout(function(){
        fn.call(context,text);
        },delay);
      }
    }

    结果如图:

    这里写图片描述

    显然,连续的输入,到一定时间间隔之后,queryData函数必然会被调用,但是又不是频繁的调用。这既达到了节流的目的,又不会影响用户体验。

    4、进一步的优化

    进一步的话,就是可以在调用throttle函数之前,先对输入的内容进行判断,若其值为空、值不变都不用再调用。

  • 相关阅读:
    android逆向奇技淫巧五:x音fiddler抓包分析协议字段
    windows:3环自行加载PE文件实现进程隐藏
    android逆向奇技淫巧四:模拟器检测和反检测
    android逆向奇技淫巧三:MT管理器替代android killer修改和重新编译smail代码/frida hook 更改so层代码
    windows运算符和数据类型重载反CE查询搜索
    android逆向奇技淫巧二:uiautomatorviewer&method profiling定位x音java层的关键代码和方法
    android逆向奇技淫巧一:去掉开屏广告
    xx课堂m3u8加密视频下载
    Python接口自动化之logging日志
    Python接口自动化之pymysql数据库操作
  • 原文地址:https://www.cnblogs.com/Zting00/p/7497670.html
Copyright © 2011-2022 走看看