一、问题
如何解决用户频繁操作所带来的性能问题?
二、场景
简书中的Markdown预览功能,希望用户停止输入0.5s后进行渲。
页面有一个搜索框,希望在用户停止输入1s后调用后台接口获取数据。
染。有一个表格,希望用户向下滚动时每隔1秒向后台发起一次请求。
三、防抖
定义:在一定时间内,在动作被连续频繁触发的情况下,动作只会被执行一次。
方案:用户在规定的时间内(假设1s)连续输入时不做任何事情,如果1s后用户没有继续输入,进行处理(向后台发请求等)。
原理: 设置一个定时器,规定1s后执行,如果1s内用户有新的输入,重新设置定时器。
代码:
/** 防抖 @param fn 回调 @param delay 延时 **/ const debounce = (fn, delay)=>{ let timer = null; return function(){ clearTimeout(timer); timer = setTimeout(()=>{ fn.apply(this, arguments) }, delay); } } element.addEventListener('input', debounce(function(){ //TODO:输入结束时做的事情 }, 1000));
四、节流
定义:在一定时间内,在动作被连续频繁触发的情况下,每隔一定时间执行一次。
方案:如果3s内用户不断的向下拉取滚动条加载数据时,我们每隔1s触发一次事件。
原理: 设置一个延时器timer,规定1s后触发,延时器内部更改timer的值。(方法很多)
代码1:
/** 节流 @param fn 回调 @param delay 延时 **/ const throttle = (fn, delay)=>{ let timer = null; return function(){ //delay时间内不能触发 if(!timer){ timer = setTimeout(()=>{ tiner = null; fn.apply(this, arguments); }, delay); } } } search.addEventListener("input", throttle(()=>{ console.log(1); }, 1000));
弊端:不能立即执行
代码2:
/** 节流 @param fn 回调 @param delay 延时 **/ const throttle = (fn, delay)=>{ let startTime = Date.now(); return function(){ //delay时间内不能触发 if(Date.now() - startTime > delay){ startTime = Date.now(); fn.apply(this, arguments); } } } search.addEventListener("input", throttle(()=>{ console.log(1); }, 1000));
弊端:不会执行最后一次
代码3(结合延时器和时间):
/** 节流 @param fn 回调 @param delay 延时 **/ const throttle = (fn, delay)=>{ let timer = null; let startTime = Date.now(); return function(){ //如果空闲时间 > delay,立即执行 if(Date.now() - startTime > delay){ startTime = Date.now(); fn.apply(this, arguments); }else{ clearTimeout(timer); timer = setTimeout(()=>{ fn.apply(this, arguments); }, delay); } } } search.addEventListener("input", throttle(()=>{ console.log(1); }, 1000));
网友评论