防抖与节流

防抖

在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。

解决方法:每次触发事件时都取消之前的延时调用方法
应用场景:实现一个搜索功能,input需要绑定onchange事件,在onchange事件里调后台接口,此时,输入一个字母就进行一次请求,连续输入就会进行很多次请求,性能不太好,这时候就需要加一个防抖,如果连续输入,就等最后一个字母输入几秒之后再调接口。
实现思路:通过闭包维护一个变量,此变量代表是否已经开始计时,如果已经开始计时则清空之前计时器,重新计时。
实现方法

//防抖debounce代码:
function debounce(fn) {
    let timeout = null; // 创建一个标记用来存放定时器的返回值
    return function () {
        // 每当用户输入的时候把前一个 setTimeout clear 掉
        clearTimeout(timeout); 
        // 然后又创建一个新的 setTimeout, 这样就能保证interval 间隔内如果时间持续触发,就不会执行 fn 函数
        timeout = setTimeout(() => {
            fn.apply(this, arguments);
        }, 500);
    };
}
// 处理函数
function handle() {
    console.log(Math.random());
}
// 滚动事件
window.addEventListener('scroll', debounce(handle));

下面是我自己写的小例子

!DOCTYPE html>  
<html lang="en">  
<head>      
	<meta charset="UTF-8">      
	<meta name="viewport" content="width=device-width, initial-scale=1.0">      
	<title>防抖</title></head>  
<body>      
	<input type="text" class="form-control" placeholder="请输入搜索关键字" id="search">  
</body>  
<script>     
	 var input = document.getElementById("search")    // 防抖debounce代码:    
	 function debounce(fn) {        
	 	let timeout = null; // 创建一个标记用来存放定时器的返回值        
	 	return function () {            
	 	// 每当用户输入的时候把前一个 setTimeout clear 掉            
	 	clearTimeout(timeout);             // 然后又创建一个新的 setTimeout, 这样就能保证interval 间隔内如果时间持续触发,就不会执行 fn 函数           
	 	timeout = setTimeout(() => {
	 	    fn.apply(this, arguments);            
	 	}, 600);      
	    };   
	 }    
	 // 处理函数   
	  function handle() {       
	     console.log("我进行请求了");    
	  }

	   //input.oninput = debounce(handle)    
	   input.addEventListener('input', debounce(handle));

</script>
 </html>

节流

高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率

解决方法:每次触发事件时都判断当前是否有等待执行的延时函数
应用场景:连续点击事件或者鼠标移动事件。里面要调接口的话,也会连续调无数次,此时加个节流,让该事件再n秒之内只执行一次。提高了性能。
实现思路:通过闭包维护一个变量,次变量代表是否允许执行函数,如果允许则执行函数并且把该变量修改为不允许,并使用定时器在规定时间后恢复变量。
实现方法

 <script>
 //节流throttle代码:
function throttle(fn) {
    let canRun = true; // 通过闭包保存一个标记
    return function () {
         // 在函数开头判断标记是否为true,不为true则return
        if (!canRun) return;
         // 立即设置为false
        canRun = false;
        // 将外部传入的函数的执行放在setTimeout中
        setTimeout(() => { 
        // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。
        // 当定时器没有执行的时候标记永远是false,在开头被return掉
            fn.apply(this, arguments);
            canRun = true;
        }, 500);
    };
}

function sayHi(e) {
    console.log(e.target.innerWidth, e.target.innerHeight);
}
window.addEventListener('resize', throttle(sayHi));
 </script>

下面是我自己写的小例子:

<!DOCTYPE html>
<html lang="en"><head>    
<meta charset="UTF-8">    
<meta name="viewport" content="width=device-width, initial-scale=1.0">    
<title>节流</title>
</head>
<body>     
    <div id="btn">点我抢购</div>
</body>
<script>    
	var btn = document.getElementById("btn");    //节流throttle代码:    
	function throttle(fn) {    
		let canRun = true; // 通过闭包保存一个标记    
		return function () {         // 在函数开头判断标记是否为true,不为true则return        
			if (!canRun) return;    // 立即设置为false        
		 	canRun = false;        // 将外部传入的函数的执行放在setTimeout中        
 			setTimeout(() => {         
		 // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。       
 		 // 当定时器没有执行的时候标记永远是false,在开头被return掉            
 			 fn.apply(this, arguments);            
 			 canRun = true;        
 			 }, 1000);    
 		 };
 	 }
  
	function sayHi(e) {    
		console.log("我抢到了,哈哈哈");
	}
	
	btn.addEventListener('click', throttle(sayHi));
</script>
</html>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值