防抖debounce和節流throttle
阿新 • • 發佈:2018-08-27
就會 listener timestamp search ron 存在 iat NPU 崩潰
大綱
一、出現緣由
二、什麽是防抖debounce和節流throttle
三、應用場景
3.1防抖
3.2節流
一、出現緣由
前端開發中,有一部分用戶行為會頻繁觸發事件,而對於DOM操作,資源加載等耗費性能的處理,很可能導致卡頓,甚至瀏覽器崩潰,防抖和節流就是為了這一類的問題出現的前端優化技術。
二、什麽是防抖debounce和節流throttle
防抖debounce是函數在規定延遲時間內不被調用,才能再次被調用,如果在規定時間內調用,延遲重新開始計算;
節流throttle是在規定的延遲時間間隔後,函數才執行一次,以固定的頻率被觸發。
三、簡單實現
3.1防抖
連續觸發事件的時候,不會有任何反應,停止觸發事件的多少秒,就會執行,在延遲時間內執行函數,就重新開始一個定時器。
function debounce(func,delay=300,timer=null){ return (...args){ clearTimeout(timer); timer=setTimeout(func.bind(null,...args,delay);) } } function query(){ //ajax } input.addEventListener(‘keyup‘,debounce(query))
3.2節流
觸發事件的時候,執行一個函數,在之後的一段時間內進這個函數,會被return,真正的邏輯不能執行,定時器在一定時間後重置開關,再進來就能再次執行真正的邏輯了。
function throttle(func,delay=60){ let lock=false; return (...args)=>{ if(lock)reutrn; function(..args); lock=true; setTimeout(()=>lock=false,delay); } } function query(){ //ajax } decument.addEventListener(‘scroll‘,throttle(query));
四、應用場景
3.1防抖throttle的應用場景
防抖適用於window.onscroll事件,等到拉動動作結束後再觸發一個事件,或者拖拽
_.throttle=function(func,wait,options){ var context,args,result; var timeout=null; var previous0; if(!options)options={} var later=function(){ previous=options.leading===false:0:new Date(); timeout=null; result=func.apply(context,args); if(!timeout)context=args=null; } return fucntion(){ var now=new Date(); if(!previous && option.leading===false)previous=now; var remaining=wait-(now-previous); context=this; args=arguments; if (remaining <= 0 || remaining > wait) { if (timeout) { clearTimeout(timeout); timeout = null; } previous = now; result = func.apply(context, args); if (!timeout) context = args = null; } else if (!timeout && options.trailing !== false) { timeout = setTimeout(later, remaining); } return result; } }
3.2節流throttle的應用場景
下面具體講一個例子
假設我們網站有一個搜索框,用戶輸入文本我們自動會聯想匹配除一些結果供用戶選擇,我首先想到的做法是監聽keypress事件或change事件,然後ajax請求數據,但是當用戶快速輸入的時候,就會瞬間觸發一連串的請求,這無疑不是我們想要的,我們想要的是用戶停止輸入的時候才去觸發查詢的請求,這時候函數防抖可以幫助我們。
_.throttle=function(func,wait,immediate){ var timeout,args,context,timestamp,result; var later=function(){ //如果沒有超過等待時間,就接著設置一個定時器,時間是delay的時間減去方法執行的時間 var last=new Date().getTime() - timestamp; if(last<wait && last>=0){ timeout=setTimeout(later,wait-last); }else{ //如果已經過wait時間了,就直接清除定時器,給result賦值 clearTimeout(timeout); if(!immediate){ result=func.apply(context.args); if(!timeout)context=args=null; } } } return function(){ context=this; args=arguments; timestamp=new Date().getTime(); var callNow=immediate && timeout; //如果是立即執行或者之前執行過還沒過延遲時間 if(!timeout)timeout=setTimeout(later,wait); //如果之前沒執行過,現在開始定時任務,如果執行過,timeout存在,就返回個空的result. if(callNow){ //如果是立即執行,就立即執行fn,這時候 console.log(1); result=func.apply(context,args); context=args=null; } return result; } } function query(){ //ajax console.log(‘ajax‘); } $("#search").keypress(_.throttle(query,300));
防抖debounce和節流throttle