首頁  >  文章  >  web前端  >  js高性能函數防手震與節流詳解

js高性能函數防手震與節流詳解

小云云
小云云原創
2018-03-17 15:01:571758瀏覽

函數節流是指一定時間內js方法只跑一次,函數防手震:是指頻繁觸發的情況下,只有足夠的空閒時間,才執行程式碼一次。本文主要和大家分享js高性能函數防手震與節流詳解,希望能幫助大家。

一.函數節流(throttle)

1.函數節流的目的
例如,DOM 操作比起非DOM 互動需要更多的記憶體和CPU時間。連續嘗試進行過多的DOM 相關操作可能會導致瀏覽器掛起,有時甚至會崩潰。尤其在IE 中使用onresize 事件處理程序的時候容易發生,當調整瀏覽器大小的時候,事件會連續觸發。在onresize 事件處理程序內部如果嘗試進行DOM 操作,其高頻率的變更可能會讓瀏覽器崩潰。又例如,我們常見的一個搜尋的功能,我們一般是綁定keyup事件,每按下一次鍵盤就搜尋一次。但是我們的目的主要是每輸入一些內容搜尋一次而已。為了解決這些問題,就可以使用定時器對函數進行節流。
2.函數節流的原理
某些程式碼不可以在沒有間斷的情況連續重複執行。第一次呼叫函數,建立一個定時器,在指定的時間間隔之後執行程式碼。當第二次呼叫函數時,它會清除前一次的計時器並設定另一個。如果前一個定時器已經執行過了,這個操作就沒有任何意義。然而,如果前一個定時器尚未執行,其實就是將其替換為新的定時器。目的是只有在執行函數的請求停止了一段時間之後才執行。

3.函數節流的基本模式

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

4.列子

<!DOCTYPE html>
<html lang="zh-CN">
<head>  
	<meta charset="utf-8">
    <title></title>  
</head>  
<body>  	
	<input id="search" type="text" name="search">
<script>

	function queryData(text){
	  console.log("搜索:" + text);
	}
	var input = document.getElementById("search");
	input.addEventListener("keyup", function(event){
	  	throttle(queryData, null,500,this.value,1000);
	});
	        
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);
  }
}
</script>
</body>  
</html>

JavaScript 節流函數Throttle 詳解

談談JS中的函數節流

二.函數防手震(debounce)

在解釋這個函數前,我們先看下範例:註冊頁面,需要驗證電話號碼。此時我們可能想到的做法就是監聽keypress事件,然後異驗證。這個方法本身是沒錯的,但是如果用戶快速的輸入了一連串的手機號碼,那麼就會在瞬間觸發了11次的請求,這無疑不是我們想要的。我們想要的是用戶停止輸入的時候才去觸發驗證的請求,這時候函數防手震可以幫我們。

function debounce(func, wait, immediate) {
    var timeout; // 持久化一个定时器
     // 闭包函数可以访问timeout
    return function() {
    	 // 通过 this 和 arguments 获得函数的作用域和参数
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout); // 如果事件被触发,清除timer并重新开始计时
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};

參數function是需要函數防手震的函數;參數wait則是需要等待的時間,單位為毫秒;immediate參數如果為true,則debounce函數會在呼叫時立刻執行一次function,而不需要等到wait這個時間後,例如防止點擊提交按鈕時的多次點擊就可以使用這個參數。

列子:

<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>函数防抖与节流 </title>
</head>
<body>
	<form class="form-cnt" action="" method="">
			<input type="text" value="" id="tel"/>
	</form>
	<script type="text/javascript" src="js/jQuery-2.1.4.min.js" ></script>
<script>
function debounce(func, wait, immediate) {
    var timeout;
    return function() {
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};

function checkTel(){
	var val = $("#tel").val();  
	 var  re = new RegExp("(^1[3|4|5|7|8][0-9]{9}$)");  
	if(re.test(val)){  
	  console.log("结果:格式正确");  
	}else{  
	    console.log("结果:格式错误");  
	}  
}  
var lazyQuery = debounce(checkTel, 300);
$("#tel").on("keypress",lazyQuery);  
</script>
</body>
</html>


#這效果就看到觸發了6次而不是11次

三.應用場景

(1).函數節流(throttle)
1. 頻繁的mousemove/keydown,例如高頻的滑鼠移動,遊戲射擊類別的
2. 搜尋聯想(keyup )
3. 進度條(我們可能不需要高頻的更新進度)
4. 拖曳的dragover等
5.  高頻的點擊,抽獎等(哈哈,邪惡)

(2).函數防手震(debounce)
 1. scroll/resize事件
 2. 文字連續輸入,ajax驗證/關鍵字搜尋

#

以上是js高性能函數防手震與節流詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn