JS高頻功能優(yōu)化之函數(shù)節(jié)流和函數(shù)防抖
一.基本概念
什么是高頻功能辖试?
“高頻”望文取義就是“很快的”劈狐;在JavaScript中,可以理解為對(duì)一個(gè)函數(shù)/事件觸發(fā)次數(shù)很多的肥缔,很快的;典型的例子就是JS中鼠標(biāo)滑輪事件,鼠標(biāo)移動(dòng)事件的觸發(fā)和輸入框聯(lián)想查詢(xún)功能實(shí)現(xiàn)等收班;
JS中為什么要減少高頻的發(fā)生呢?
一句話(huà)總結(jié):“減少高頻摔桦,節(jié)約資源,防止體驗(yàn)差”邻耕;
- 節(jié)約開(kāi)銷(xiāo):輸入框的聯(lián)想搜索功能,百度搜索就有聯(lián)想搜索功能燕鸽;聯(lián)想搜索功能的實(shí)現(xiàn),是通過(guò)監(jiān)聽(tīng)用戶(hù)輸入去想后臺(tái)請(qǐng)求相應(yīng)的列表啊研,并加以展示出來(lái);代碼如下:
var seardom=document.getElementById("search");
var sear_list=[]; //定義聯(lián)想搜索列表
seardom.addEventListener("keyup",function(){ //keyup事件在鍵盤(pán)按鍵釋放時(shí)觸發(fā)
//由于ajax是異步的党远,并具有一定的延時(shí)性,所以通過(guò)setTimeout表示數(shù)據(jù)請(qǐng)求
setTimeout(function(res){//res表示后臺(tái)返回的數(shù)據(jù)
sear_list=res.datas; //后臺(tái)返回的聯(lián)想搜索列表
},2000);
});
上述代碼是個(gè)Demo麸锉,通過(guò)以上代碼可知舆声,每次鍵盤(pán)按鍵釋放時(shí)就會(huì)觸發(fā)請(qǐng)求,這就是個(gè)“高頻”的動(dòng)作媳握;會(huì)造成沒(méi)必要的HTTP請(qǐng)求資源浪費(fèi);
- 防止體驗(yàn)差:拖拽功能實(shí)現(xiàn)蛾找,現(xiàn)在有很多網(wǎng)頁(yè)都擁有拖拽功能;比如網(wǎng)頁(yè)版的照片查看器打毛,就去要對(duì)圖片進(jìn)行拖拽查看;如果沒(méi)做優(yōu)化處理幻枉,那么拖拽過(guò)程中會(huì)出現(xiàn)卡頓,不靈活等體驗(yàn)性差的問(wèn)題熬甫;
二.怎樣用JS解決高頻問(wèn)題呢?
如果不通過(guò)第三方框架處理高頻問(wèn)題,如RXJS異步框架瞻颂;只用JS來(lái)處理高頻,那么就需要函數(shù)節(jié)流和函數(shù)防抖這兩種方案贡这;
1.什么是函數(shù)節(jié)流?
函數(shù)節(jié)流就是在一定時(shí)間內(nèi)只能執(zhí)行做一件事情(這里的事情指的是重復(fù)的事情)藕坯;例如:吃飯,飯要一口一口吃炼彪,等一口咽下去了就吃下一口,如果一口沒(méi)咽下去就急忙吃下一口辐马,就容易咽卓介佟冗疮;在實(shí)現(xiàn)某些功能的時(shí)候,程序也是如此檩帐;如上訴所說(shuō)的圖片拖拽功能;
實(shí)現(xiàn)要點(diǎn):通過(guò)定義一個(gè)標(biāo)識(shí)來(lái)記錄某函數(shù)是否在執(zhí)行湃密,如果在執(zhí)行,就return false泛源;如果沒(méi)有執(zhí)行,就執(zhí)行該方法达箍;代碼如下:
var dom=document.getElementById("dom"); //需要拖拽的dom
var isBool=false; //定義是否執(zhí)行的標(biāo)識(shí)
dom.addEventListener("mousemove",function(){ //監(jiān)聽(tīng)鼠標(biāo)移動(dòng)件
if(isBool){//true在執(zhí)行,false沒(méi)有執(zhí)行
return false;
}
isBool=true;
setTimeout(function(){//設(shè)置定時(shí)函數(shù)setTimeout缎玫,每60ms執(zhí)行一次
isBool=false;
//dosomething......
},60);
});
2.什么是函數(shù)防抖?
函數(shù)防抖就是在一定時(shí)間內(nèi)要連續(xù)不斷的做一件事赃磨,前提是清除前面正在做的事情(這里的事情是指重復(fù)的事情);例如:吃飯煞躬,正常人吃飯的程序是在一定時(shí)間內(nèi)逸邦,一口咽下去再吃下一口(函數(shù)節(jié)流),非正常人吃飯的程序是在一定時(shí)間內(nèi)當(dāng)一口還沒(méi)咽下去缕减,然后來(lái)了下一口飯的時(shí)候,就將上一口飯給吐出來(lái)桥狡,一直重復(fù)此動(dòng)作,一直到最后一口飯才咽下去(函數(shù)防抖)皱卓。請(qǐng)勿模范,后果自負(fù)娜汁;
實(shí)現(xiàn)要點(diǎn):通過(guò)setTimeout()實(shí)現(xiàn)延時(shí)執(zhí)行某方法,例如延時(shí)時(shí)間2s掐禁,如果2s范圍內(nèi)接著執(zhí)行該方法,就需要用clearTimeout()方法清除上一個(gè)setTimeout的延時(shí)執(zhí)行的方法傅事;代碼如下:
var seardom=document.getElementById("search");
var sear_list=[]; //定義聯(lián)想搜索列表
var timeout=null;
seardom.addEventListener("keyup",function(){ //keyup事件在鍵盤(pán)按鍵釋放時(shí)觸發(fā)
if(timeout != null){ //timeout!=null的時(shí)候,清除上個(gè)延時(shí)的方法
clearTimeout(timeout);
}
timeout=setTimeout(function(res){//res表示后臺(tái)返回的數(shù)據(jù)
sear_list=res.datas; //后臺(tái)返回的聯(lián)想搜索列表
},2000);
});
三.函數(shù)節(jié)流和函數(shù)防抖的不同性總結(jié):
其實(shí)就是一句話(huà)“節(jié)流做事有始有終蹭越,要排隊(duì);防抖做事始亂終棄响鹃,也要排隊(duì)”;但是節(jié)流和防抖有個(gè)共性茴迁,就是做的事情都是一樣一樣的萤衰;
“節(jié)流做事有始有終,要排隊(duì)”:就是等上一件事情做完脆栋,才能做下一件事情倦卖;
“防抖做事始亂終棄怕膛,也要排隊(duì)”:上一件事情還沒(méi)做完,就清除上件事情做下一件事情秦踪;