对“帕金森”say no !
/* debouce:防抖
* @params
* - func : 最终要执行的函数
* - wait : 自定义频率 默认300ms
* - immediate : 设置触发边界,为true在开始边界除触发,默认在结束边界触发
* @return
* - func函数执行的返回结果
* update 2021/01/27 by qiancan
*/
const debounce = function debounce(func, wait, immediate) {
if (typeof func !== 'function') throw new TypeError('func must be require and be a function!');
if (typeof wait === 'boolean') {
immediate = wait;
wait = 300;
}
if (typeof wait !== 'number') wait = 300;
if (typeof immediate !== 'boolean') immediate = false;
let timer = null,
result;
return function proxy() {
var runNow = !timer && immediate,
params = [].slice.call(arguments),
self = this;
if (timer) clearTimeout(timer);
timer = setTimeout(function () {
if (timer) {
clearTimeout(timer);
timer = null;
}
!immediate ? result = func.apply(self, params) : null;
}, wait);
runNow ? result = func.apply(self, params) : null;
return result;
};
};
如果
immediate是false,runnow就是false。func函数就是结束边界触发,反之为true在开始边界触发。
如果在300ms内,没有触发第二次点击,则只设定一个定时器,在wait时间后将func函数执行。并且将这个定时器也清除掉,同时赋值为null。如果不赋值为null,定时器虽然清了,但是timer还是有值的。如果开始边界执行,func将无法再次执行。func需要在开始边界执行,前提runnow需要为true。而runnow为true的前提条件是timer为null。
如果300ms内发生多次点击,结果就是会产生很多的定时器,wait时间到后这些定时器一一执行。如果在300ms内第二次点击了,此时timer不为null,清除定时器操作执行。这一次重复点击生成的定时器会在下一次重复点击时清掉,直到wait时间不再发生多次点击为止。最后会留下一个定时器,也会被销毁。300ms开始边界触发同理。发生多次没次都会清除定时器,并且将最后剩下一个定时器执行时赋值为null,runow才能让func再次执行。(当前有定时器runnow就是false)
函数“变频器”
/* throttle:节流
* @params
* - func : 最终要执行的函数
* - wait : 自定义频率 默认300ms
* @return
* - func函数执行的返回结果
* update 2021/01/27 by qiancan
*/
const throttle = function throttle(func, wait) {
if (typeof func !== 'function') throw new TypeError('func must be require and be a function');
if (typeof wait !== 'number') wait = 300;
var timer = null,
previous = 0,
result;
return function proxy() {
var self = this,
params = [].slice.call(arguments),
now = +new Date(),
remaining = wait - (now - previous);
if (remaining <= 0) {
if (timer) {
clearTimeout(timer);
timer = null;
}
result = func.apply(self, params);
previous = + new Date();
} else if (!timer) {
timer = setTimeout(function () {
if (timer) {
clearTimeout(timer);
timer = null;
}
result = func.apply(self, params);
previous = +new Date();
}, remaining)
}
return result;
};
};
控制触发频率。当设定频率内发生重复操作会被忽略,本来5ms后能执行第二次,现在让
wait才能执行第二次。previous最初为0,用于保存当前这次点击的时间,用于和下一次的点击时间进行处理得到两次点击的时间差,拿两次时间差再去和wait判断第二次点击操作是否发生在wait时间内。如果时间差值比wait大,说明第二次点击发生在wait时间后,remaining小于等于0允许执行func。如果wait比时间差的时间大,说明第二次点击发生wait时间内=>设定定时器,过了remaining时间再去执行func。每次执行func,都要求把previous更新,比较最新的上一次。第一次func执行更新了previous。在第一次触发10毫秒后第二次触发了,和第一次时间差10ms,假设当前wait500ms,设置490ms定时器490ms后执行func。第二次点击生成的定时器在时间未到之前,previous未为被更新。当第二次相隔10ms,紧接着发生了第三次点击。得到的时间差还是和第一次的previous在比较,相当于500-20ms,又设置480ms定时器。490、480、470、460,只是在重复设定定时器。当没有达到间隔时间,同时之前没有定时器才设置定时器是合适的。定时器执行时清除定时器同时赋timer为null,让下次能够重新设置定时器。