函数节流(throttle)与函数去抖(debounce)记录
2018-12-21 本文已影响0人
chouchou723
1.函数节流:
如果将水龙头拧紧直到水是以水滴的形式流出,那你会发现每隔一段时间,就会有一滴水流出。
也就是会说预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期。
#throttle使用场景
第一次触发后先执行fn(当然可以通过{leading: false}来取消),然后wait ms后再次执行,在单位wait毫秒内的所有重复触发都被抛弃。即如果有连续不断的触发,每wait ms执行fn一次。与debounce相同的用例,但是你想保证在一定间隔必须执行的回调函数。例如:
对用户输入的验证,不想停止输入再进行验证,而是每n秒进行验证;
对于鼠标滚动、window.resize进行节流控制。
简单实现:
var throttle = function(delay, action){
var last = 0;
return function(){
var curr = +new Date()
if (curr - last > delay){
action.apply(this, arguments)
last = curr
}
}
}
完整实现:
export default (fn, delay = 100) => {
let now, lastExec, timer, context, args
function execute() {
fn.apply(context, args)
lastExec = now
}
return function() {
context = this
args = arguments
now = + new Date()
if (timer) {
clearTimeout(timer)
timer = null
}
if (!lastExec) {
execute()
} else {
var diff = delay - (now - lastExec)
if (diff < 0) {
execute()
} else {
timer = setTimeout(function() {
execute()
}, diff)
}
}
}
}
两者差别主要在于,简单实现是大于delay才会执行(也就是你两次滚动的间隔要大于delay),但是两次如果小于delay,则完全不会执行,而完整实现是即使两次滚动间隔小于delay,也会有一个定时器进行执行,防止你在第二次滚动之后,没有再滚动
2.debounce
如果用手指一直按住一个弹簧,它将不会弹起直到你松手为止。
也就是说当调用动作n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间。
debounce使用场景:
第一次触发后,进行倒计wait毫秒,如果倒计时过程中有其他触发,则重置倒计时;否则执行fn。用它来丢弃一些重复的密集操作、活动,直到流量减慢。例如:
对用户输入的验证,不在输入过程中就处理,停止输入后进行验证足以;
提交ajax时,不希望1s中内大量的请求被重复发送。
简单实现:
var debounce = function(idle, action){
var last
return function(){
var ctx = this, args = arguments
clearTimeout(last)
last = setTimeout(function(){
action.apply(ctx, args)
}, idle)
}
}