throttle【节流】
- 间隔时间执行;通过判断是否到达一定的时间来触发函数,若没有到达规定的时间则使用定时器延后,而下一次事件则重新设计定时器;
- 一个单位时间内,只能有一次事件的回调函数执行,如果同一单位时间内某事件被触发多次,只有一次能生效;
- 应用场景:页面无线加载场景下,需要用户滚动页面,每隔一段时间发送一段请求,而不是在用户停下,滚动页面时才去请求数据,用户滑倒页面底部自动加载更多,使用节流进行判断
<input type="text" id="ipt">
window.onload = function () {
//模拟ajax请求
function ajax(content) {
console.log('ajax request ' + content)
}
function throttle(fun, delay) {
// last【最后的】;deferTimer【延时定时器】
let last, deferTimer
return function (args) {
let that = this;
let _args = arguments;
// 每次触发都会获取当前的最新时间戳
let now = +new Date();
// last记录定时器的时间戳
// 大部分事件触发都是走这个分支;用于确保最后一次触发
if (last && now < last + delay) {
clearTimeout(deferTimer);//清除延时定时器,重新设置定时器
//用于延时定时器
deferTimer = setTimeout(function () {
last = now;
fun.apply(that, _args);
}, delay)
//【1.首次触发,立即执行;2.超出delay(也就是正常点击)】;【注】通过判断是否到达一定的时间(delay)来触发函数
}else{
last = now;
fun.apply(that, _args);
}
}
}
let throttleAjax = throttle(ajax, 1000)
let inputThrottle = document.getElementById('ipt')
inputThrottle.addEventListener('keyup', function (e) {
throttleAjax(e.target.value)
})
}
function handler() {
console.log('123');
}
第二种
function throttle(func, wait) {
let lastTime = null
let timeout = null
return function () {
let context = this
let now = Date.now()
console.log(timeout,'timeout');
// 如果上次执行的时间和这次触发的时间大于一个执行周期,则执行;首次执行
if (now - lastTime - wait > 0) {
// 如果之前有了定时任务则清除
console.log('1');
console.log(timeout);
if (timeout) {
clearTimeout(timeout)
timeout = null
}
func.apply(context, arguments)
// 这里lastTime是上次的触发时间
lastTime = now
} else if (!timeout) {
console.log('2');
console.log(timeout);
timeout = setTimeout(() => {
// 改变执行上下文环境
func.apply(context, arguments)
}, wait)
}else{
console.log(timeout,'3');
}
}
}
简易节流
function throttle1(func, wait) {
let lasttime = null;
return function () {
let now = Date.now()
// 如果上一次的执行时间和这次的触发时间大于一个周期则执行
if (now - lasttime - wait > 0) {
func()
lasttime = now;
}
}
}
防抖
- 某一段时间内只执行一次;维护一个定时器,规定在delay时间内再次触发,都会清除定时器
- 当前的timer然后重新设置超时调用,只有最后一次操作才能被触发;
- 应用场景:用户在输入框中连续输入一串字符后,只会在输入完后去执行最后一次查询请求,
- 这样可以有效减少请求次数,节约请求资源,window的reszie,scroll事件
- 每一次事件被触发,都会清除当前的timer并重新设置超时调用,重新计时;