前言无论是面试还是讨论浏览器优化,总会涉及到debounce和throttle的问题。总的来说,这两者是一种限制事件触发频率的方法。不同之处在于节流指定了事件触发的时间间隔;debounce指定事件不触发的时间间隔。从结果来看,节流降低了时间处理的敏感性;而去抖对首先从触发事件开始存储,并在超过指定的事件间隔后一起发送。晕了,直接上代码:HTML这里是一个input标签,供用户搜索,还有一个处理函数,会被input事件触发。这个fatch会根据输入的值,向后台请求关联词。上面的代码思路没有问题,但是如果没有触发限制,可能会产生大量的http请求,而其中很多请求可能没有意义,这就为我们的优化提供了空间;下面,我将使用节流和两种方法来解决这个问题。(一般是input的情况,使用debounce解决;这里只是为了方便代码描述)throttlingfunctionjieliu(func,time){//func执行函数,时间间隔now=newDate()if(now-lastRun>time){func(...arguments)lastRun=now}}}constlistener=jieliu(function(value){//监听函数,指定间隔时间console.log(value)},1000)constinput=document.querySelector("input")//调用方法input.addEventListener("input",function(event){listener(event.target.value)})上面是比较简单的节流实现和基本调用方法;闭包的用途是保存每次执行的lastRun。限制请求频率的要求基本实现了,只是忽略了最后一个触发。改进如下:functionjieliu(func,time){//触发时间间隔>time发送请求letlastRun=nulllettimeout=undefinedreturnfunction(){constself=this;constnow=newDate()if(now-lastRun>time){if(timeout){clearTimeout(timeout)timeout=undefined}func.apply(self,arguments)lastRun=now}else{if(!timeout){超时=setTimeout(func.apply(self,arguments),time)}}}}添加超时判断是否为最后一次请求。Debouncefunctionqudou(func,time){lettimeout=undefinedreturnfunction(){constargu=argumentsconstself=thisif(timeout){clearTimeout(timeout)timeout=undefined}else{timeout=setTimeout(func.apply(this,arguments),time)}}}上面debounce的简单实现,同样,最后一个事件不能触发处理函数。改进如下:functionqudou(func,time){//判断在连续的时间段内不触发,发送func请求lettimeout=undefined;让lastRun=nullreturnfunction(){constself=thisconstnow=newDate()if(now-lastRun>time){func.apply(self,arguments)}else{if(!timeout){timeout=setTimeout(func.apply(self,arguments),time)}else{clearTimeout(timeout)timeout=undefined}}lastRun=newDate()}}总结整篇文章,实现节流的主要方式是比较时间差在“now”和“lastRun”之间,从而减少对处理函数的调用次数;而防抖依然是通过settimeout延迟调用处理函数的时机,然后聚合多次触发的结果来调用处理函数。后记节流和去抖的方案还是有很大区别的,包括我在内的很多人很容易混淆。如果您有更好的解决方案或需要讨论,欢迎留言!