1,节流
节流就是对连续的函数触发,在设定的间隔时间段内,只让其执行一次。
先来看看js高级程序设计3里面节流的代码
function throttle (method, context, wait) { ???clearTimeout(method.tId) ????method.tId = setTimeout(function () { ????????method.call(context) ????}, wait)}
当函数连续执行的时候,如果之前的定时器还没执行,就把它清除了,再从新设置一个新的定时器。
我们可以对这个进行改进
function throttle (fn, wait) {
??let timeout;
??let prevTime = 0;
??return (...args) => { ???//返回一个函数
??????let now = new Date;
??????let remaining = wait - (now - prevTime) ????// 下一次执行的时间,
??????if (remaining <=0 || remaining > wait) { ???// 如果下一次的时间小于等于0,立刻执行一次函数,并把时间戳改为当前的时间。
??????????clearTimeout(timeout)
??????????timeout = null
??????????prevTime = now
??????????fn(args)
??????} else if (!timeout) { ?????????// 如果当前没有定时器 那么就新加一个定时器。
??????????timeout = setTimeout(() => {
??????????????timeout = null;
??????????????prevTime = new Date;
??????????????fn(args)
??????????}, remaining)
??????}
??}
}
第一次执行: timeout为undefined, prevTime为0 remaining为负数,走if的第一个,立即执行了函数并将下次时间改成当前时间
第二次执行: 下一次时间为正,定时器还是为undefined,走if的第二个,设置定时器
下一次执行(不超过wait时间内) : remaining大于0,定时器为true,所以直接跳出
understore里面的节流考虑了两个高级的配置: 是否在第一次触发的时候就执行函数 和 最后一次的定时器触发的执行函数。还提供了节流的取消函数。
function throttle(fn, wait, option = {}) { ???????let timeout; ???????let prevTime = 0 ???????let throttled = (...args) => { ???????????let now = new Date; ???????????if (!prevTime && option.leading === false) prevTime = now; ???????????let remaining = wait - (now - prevTime); ???????????if (remaining <= 0 || remaining > wait) { ???????????????if (timeout) { ???????????????????clearTimeout(timeout) ???????????????????timeout = null; ???????????????} ???????????????prevTime = now ???????????????fn(args) ???????????} else if (!timeout && option.trailing !== false) { ???????????????timeout = setTimeout(() => { ???????????????????prevTime = option.leading === false ? 0 : new Date; ???????????????????fn(args) ???????????????}) ???????????} ???????} ???????throttled.cancel = () => { ???????????clearTimeout(timeout); ???????????prevTime = 0; ???????????timeout = null; ???????} ???????return throttled}
除了加了两个配置项和取消函数,别的基本都是一样的。
需要注意的是,首次不执行和最后不执行这两个不能同时配置,只能配置一个。
2,防抖
其实我感觉防抖和节流差别不大,主要的差别在于: 在wait的时间内,反复触发函数的话,节流不会理会这些,而防抖的话,只要你触发了,他就会清除之前的定时器,从新设置一个定时器。
比如说坐电梯,如果是节流的话,电梯等待时间为5S,从第一个人进电梯开始算,到5S后他就会关门运行。
如果是防抖的话,电梯等待时间为5S,在这5S之内,如果有人进电梯,他就会重新计时,只有在5S中没有人进电梯了,电梯才关门运行。
function debounce (fn, wait) {
??let timeout;
??return (...args) => {
??????if (timeout) clearTimeout(timeout);
??????timeout = setTimeout(() => {
??????????fn(args)
??????}, wait)
??}
}
返回一个函数, 先清除之前的定时器,然后再新加定时器。
underscore里面的防抖添加了一个高级配置,是否立即执行一次函数。
function debounce(fn, wait, immediate) { ??????let timeout; ??????return (...args) => { ??????????let callNow = immediate && !timeout; ??????????if (timeout) clearTimeout(timeout); ??????????timeout = setTimeout(() => { ??????????????timeout = null; ??????????????if (!immediate) fn(args) ??????????}, wait) ??????????if (callNow) fn(args) ??????}}
这里添加了immediate这个配置项,如果为true的话,那么触发第一次的时候就执行了要执行的函数,定时器里面不执行。
js的节流和防抖
原文地址:https://www.cnblogs.com/wjyz/p/10225193.html