当前位置: 首页 > 后端技术 > Node.js

防抖和节流

时间:2023-04-03 19:29:22 Node.js

窗口调整大小、滚动、输入框内容验证等操作,如果这些操作处理功能比较复杂或者页面频繁重新渲染,在这种情况下,如果事件触发频率不限,将增加浏览器的负担,导致非常糟糕的用户体验。此时,我们可以使用debounce(防抖)和throttle(油门)的方法,在不影响实际效果的前提下降低触发频率。防抖在事件触发后n秒执行,在此期间如果再次触发事件,将重新开始计时。我们模拟表单数据的输入,自动获取后台数据,关联搜索,反馈给前台。监听keyup事件。如果每输入一个字符就发送一个请求,会在很短的时间内发送很多请求,后台服务器会不堪重负!//监听输入值进行模糊搜索,防止不断搜索//需要触发的函数functiondebounce(d){console.log("associativesearchphoneNumber:"+d)}letinp=document.querySelector("#phone");//由输入函数触发的事件getPhone(fn,delay){lettimer;//使用闭包保证每次使用的定时器都是相同的return(d)=>{clearTimeout(timer);timer=setTimeout(()=>{fn(d);//清除定时器clearTimeout(timer);},delay)}}letgetPhoneDebounce=getPhone(debounce,1000);inp.addEventListener('keyup',(e)=>{getPhoneDebounce(e.target.value);})立即执行版本是指事件触发后立即执行函数,然后函数可以继续如果在n秒内没有触发事件,则执行Effect。/***@paramfuncfunction*@paramwait以毫秒为单位延迟执行*@paramimmediatetrue表示立即执行,false表示非立即执行*/functiondebounce(func,wait,immediate){vartimeout;返回函数(){varcontext=this;var参数=参数;如果(超时)clearTimeout(超时);如果(立即){varcallNow=!timeout;timeout=setTimeout(function(){timeout=null;},wait)if(callNow)func.apply(context,args)}else{timeout=setTimeout(function(){func.apply(context,args)},等待);}}}throttling执行一个事件。我们模拟射击。首先,当我们第一次点击射击时,我们发射了一颗子弹。当我们在很短的时间内再次点击拍摄时,由于需要‘降温’——也就是节流,再次点击是无效的。当冷却时间结束后,再次点击shot继续下一次拍摄准备工具:一个拍摄功能shot,一个功能nextShot判断拍摄间隔是否结束,一个按钮触发拍摄,一个timer判断射击是否结束基本思路:首先当按钮第一次被点击时,触发射击。连续点击该按钮时,拍摄无效,必须经过定时器设定的时间后才能继续拍摄。//模拟射击Shotfunctionshot(){console.log('shoot')}letbtn=document.querySelector('#shot');functionnextShot(fn,delay){让计时器;//闭包原理同上return()=>{//定时器存在,不能拍摄}else{//定时器不存在,拍,并设置定时器fn();timer=setTimeout(()=>{//定时器结束,可以射击clearTimeout(timer);timer=null;},delay)}}}letstart=nextShot(shot,20);btn.addEventListener('click',()=>{start();})节流分为时间戳版本和定时器版本。timestamp版本是指在事件持续触发的过程中,函数会立即执行,每1s执行一次。constthrottle=(func,wait,...args)=>{让pre=0;返回函数(){constcontext=this;让现在=Date.now();if(now-pre>=wait){func.apply(context,args);pre=Date.now();}}}定时器版本是指在不断触发事件的过程中,函数不会立即执行,每隔1s执行一次,停止触发事件后,函数会再次执行。constthrottle=(func,wait,...args)=>{让超时;返回函数(){constcontext=this;if(!timeout){timeout=setTimeout(()=>{timeout=null;func.apply(context,args);},wait)}}}其实timestamp版本的节流功能和定时器版本是时间戳版本的函数在时间段开始时触发,而定时器版本的函数在时间段结束时触发。两者结合后的版本如下:~~~~/***@descfunctionthrottling*@paramfuncfunction*@paramwaitdelayexecutioninmilliseconds*@paramtype1表示时间戳版本,2表示定时器版本*/functionthrottle(func,wait,type){if(type===1){varprevious=0;}elseif(type===2){var超时;}returnfunction(){varcontext=this;var参数=参数;if(type===1){varnow=Date.now();if(now-previous>wait){func.apply(context,args);以前=现在;}}elseif(type===2){if(!timeout){timeout=setTimeout(function(){timeout=null;func.apply(context,args)},wait)}}}}参考文章来源:《后台请求数量爆炸,没做好防抖与节流》《防抖和节流原理分析》