js 之防抖与节流 详解

防抖和节流

防抖、节流主要是用来处理某些操作,导致函数和接口的过频响应。其主要原理是利用适当的延迟和屏蔽,来避免出现过度调用出现卡顿和性能的损耗。下面我将分别对这两种方法的使用、适用场景和特性进行分析。

 

防抖(debounce)

其实debounce更贴切的说应该是一种截留。当程序为了获取用户的某项操作是,为了能够准确的得到数据变化,不得不实时监测一些数据从而导致函数和接口的频繁响应。然而有些时候对于用户和程序起到真正有作用的,却往往只有阶段性的变化结果或者是最终结果。

例如:1.滚动条滚动触发 scroll 计算 显示置顶按钮  

           2.搜索引擎的输入框 change 的智能提示

这时候我们就可以当事件被触发时,设定一个周期延迟执行动作,若期间又被触发,则重新设定周期,直到周期结束,执行动作 这就是debounce的基本思路。当然不排除某些时候也会有执行初期 立即响应的情况然后再开始延期,对于这种情况我们称它为前缘debounce。

 

延迟debounce 示意图:

前缘debounce 示意图:

防抖示例 代码  

var timer = null;
var movefun=function(){
	timer && clearTimeout(timer);
	timer = setTimeout(function() {
	    console.log('触发事件');
	}, 1000);
}
window.document.onmousemove=movefun

增加前缘触发 代码


	var debounce = (fn, wait, immediate=false) => {
		let timer, startTimeStamp=0;
		let context, args;
	 
		let run = (timerInterval)=>{
			timer= setTimeout(()=>{
				// 定时器执行 获取当前时间 
				let now = (new Date()).getTime();
				// 当前时间 和最后一次的触发时间差
				let interval=now-startTimeStamp
				//这里比较难理解 这个 其实是 将定时器的创建时的定时时间 与最后一次触发的时间与当前时间差的大小判断 
				//其实这个是可以用==来判断创建当前定时器的那次触发就是最后一次触发 单为避免执行误差 所以使用了< 
				if(interval<timerInterval){ // the timer start time has been reset,so the interval is less than timerInterval
					console.log('debounce reset',timerInterval-interval);
					startTimeStamp=now;
					// 重置定时器 并以最后一次触发时间和最初的定时时间做差值以确保准确
					run(wait-interval);  // reset timer for left time 
				}else{
					if(!immediate){
						fn.apply(context,args);
					}
					clearTimeout(timer);
					timer=null;
				}
				
			},timerInterval);
		}
	 
		return function(){
			context=this;
			args=arguments;
			let now = (new Date()).getTime();
			//每次触发 事件记录当前触发时间 
			startTimeStamp=now; // set timer start time
	 
			if(!timer){
				console.log('debounce set',wait);
				if(immediate) {
					fn.apply(context,args);
				}
				//第一次创建定定时器 时间为 创建时传入的 wait 时间
				run(wait);    // last timer alreay executed, set a new timer
			}
			
		}
	 
	}
	window.document.onmousemove=debounce(function(){alert("111111")},1000)

 

 

节流(throttling)

在一定时间内只准许执行一次,即使过多操作也会被屏蔽 。直到上一次周期方法结束,下一次才会被准许调用。 这个操作其实更像是一个定时锁 。

例:获取验证码 一般都会有个60秒倒计时 60秒以后方可再次获取

节流 示意图

前缘节流

节流示例 代码

var lastTime = null, nowTime = null,gapTime=1000;
	var moveFunc = function() {
		nowTime = new Date().getTime();
		if(nowTime - lastTime > gapTime || !lastTime) {
			console.log('请求接口返回搜索内容。。。');
			lastTime = nowTime;
		}
	}
window.document.addEventListener("mousemove",moveFunc )

 增加前缘触发 代码


	var throttling = (fn, wait, immediate) => {
		let timer, timeStamp=0;
		let context, args;
	 
		let run = () => {
			timer=setTimeout(()=>{
				if(!immediate){
					fn.apply(context,args);
				}
				clearTimeout(timer);
				timer=null;
			},wait);
		}
	 
		return function () {
			context=this;
			args=arguments;
			if(!timer){
				console.log("throttle, set");
				if(immediate){
					fn.apply(context,args);
				}
				run();
			}else{
				console.log("throttle, ignore");
			}
		}
	 
	}

其实防抖和节流都可以在高频事件中起到节约资源的作用。当然其中还是略有不同的,大家要根据个人的业余需求去适用。

比如 节流 就很有可能忽略最后一次的触发事件、而防抖可能导致事件只执行一次,两个方法的侧重点不同。

总结:

         防抖:注重最后一次触发的执行效果

         节流:注重执行效果的规则和平滑性

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值