防抖(debounce)和节流(throttle)的原理以及实现
- 在平时开发的过程中,会有很多场景会频繁触发事件,比如说搜索框的实时发请求,疯狂点轮播图换图,onmousemove,resize,onscroll等等,有些时候,我们并不能或者不想频繁触发事件,咋办呢?
- 应用场景
- resize时间
- input输入发起请求
- 元素的拖动等等
防抖
原理
-
事件相应函数在一段时间后才执行,如果在这段事件内再次调用,则重新计算执行时间;当预定的时间内没有再次调用该函数,则执行dosomething函数
- undercode里面的库可以做防抖
1.假如两次间隔小于wait
2.不停移动鼠标会循环触发debounce函数
3.每次进去都会清理掉上次的定时器
4.那么就会在上一次的定时器内的回调执行前把这个定时器清理掉
<script src="https://cdn.bootcss.com/underscore.js/1.9.1/underscore.js">
<script>
let count = 0;
let container = document.querySelector("#container");
function doSomeThing (){
//这时候可能会做回调或者ajax请求
container.innerHTML = count ++;
}
container.onmousemove = _.debounce(doSomeThing,300);
</script>
- 防抖函数的初步实现
//防抖的函数
function debounce(func,wait,immediate){
let timeout;
return function(){
//这里利用了闭包
clearTimeout(timeout);
if(immediate){
//立即执行
let callNow = !timeout;
//如果是第一次点的话,timeout是没有值的
timeout = setTimeout(function(){
timeout = null;
},wait);
if(callNow){
func();
}
}
else{
//不会立即执行
timeout = setTimeout(func(),wait);
}
}
}
let count = 0;
let container = document.querySelector("#container");
//为了展示事件是如何频繁发生
function doSomeThing (){
container.innerHTML = count ++;
}
container.onmousemove = debounce(doSomeThing,300,true);
//注意这时候debounce的agruments装的是事件对象mousemove
//这个true是为了一开始立即执行
节流
原理
- 如果你持续触发事件,每隔一段时间,只执行一次事件
//这里是利用undercode
<script src="https://cdn.bootcss.com/underscore.js/1.9.1/underscore.js">
<script>
let count = 0;
let container = document.querySelector("#container");
function doSomeThing (){
//这时候可能会做回调或者ajax请求
container.innerHTML = count ++;
}
container.onmousemove = _.throttle(doSomeThing,2000,{
leading:false,
//禁用第一次执行
trailing:false
//禁止最后一次多一次执行
//官方两者不能同时用
});
</script>
-
实现方式
- 时间戳(第一次会触发,结尾不触发)
function throttle(func,wait){ //之前的时间戳 let old = 0; return function(){ //获取当前的时间戳 let now = new Date().valueOf(); if(now - old > wait){ //立即执行 func(); old = now; } } }
- 定时器(第一次不会触发,最后那下会触发)
function throttle(func,wait){ let timeout; return function(){ if(!timeout){ timeout = setTimeout(function(){ func(); timeout = null; },wait); } } }
-
需要取消操作,只需要里面加个判断条件
-
在debounce和throttle中var result,在reture的函数中result在里面获得值,最后再在这个函数中返回想要的结果