//节流函数:如果持续触发事件,每隔一段时间,只执行一次事件,时间戳和定时器两种方式实现
//1.用时间戳实现:第一次调用时间戳,减去上次的时间戳,当大于wait,则执行函数,并更新上次时间戳,如果
// 小于,则不执行
// 第一次调用能立即执行,但是结束调用不能执行最后一次
function throttleWithDate(func, wait = 1000) {
let preDate = 0;
return (args) => {
let curDate = + new Date(); //把Date对象转化为时间戳,相当于new Date().valueOf()
console.log('curDate:', curDate);
if (curDate - preDate > wait) {
func(args);
preDate = + new Date();
}
}
}
function realExecute() {
console.log('real execute: ' + new Date().valueOf());
}
// document.getElementById('testButton')
// .addEventListener('click', throttleWithDate(realExecute));
//2.用定时器实现:第一次调用开始计时,下次调用超过了wait时间,则执行函数,重新定时,否则,什么也不干
// 第一次调用不能立即执行,结束调用还能执行一次
function throttleWithTimer(func, wait = 1000) {
let timer = null;
return (args) => {
if (!timer) {
timer = setTimeout(() => {
func(args);
timer = null;
}, wait);
}
}
}
//3.结合定时器和时间戳,实现第一次调用能立即执行,且结束调用还能最后执行一次
function throttle(func, wait = 2000) {
var timer;
var preDate = 0;
var throttled = function(args) {
let curDate = + new Date();
//下次触发 func 剩余的时间,用于第一次之后的timeout执行定时
var remaining = wait - (curDate - preDate);
// 如果调用函数时时间戳,减去上次的时间戳,当大于wait,则执行函数,并更新上次时间戳
if (curDate - preDate > wait) {
console.log('时间戳执行'); //第一次执行是时间戳执行
if (timer) {
clearTimeout(timer);
timer = null;
}
preDate = curDate;
func(args);
} else if (!timer) { //这里用else,是因为时间戳执行和timeout执行只能有一个执行
timer = setTimeout(() => {
console.log('timeout执行'); //除了第一次,之后都是timeout执行
preDate = +new Date();
timer = null;
func(args)
}, remaining);
}
};
throttled.cancel = function() {
clearTimeout(timer);
timer = null;
preDate = 0;
};
return throttled;
}
let th = throttle(realExecute);
document.getElementById('testButton')
.addEventListener('click', th);
document.getElementById('cancelButton')
.addEventListener('click', th.cancel);
节流函数
最新推荐文章于 2024-04-03 13:08:44 发布