防抖和节流的实现

防抖

  • 触发函数后多长时间没再次触发,执行一次函数,如果再次触发重新开始计时
  • 常用于 key resize 等高频事件,输入框输入值时的本地缓存和异步请求
// 当页面发生滚动的时1s后执行函数
var timer = null;
window.addEventListener('scroll', function() {
    if(timer) clearTimeout(timer);
    timer = setTimeout(function() {
        console.log('我是a函数');
    }, 1000)
});

// 把函数抽出来
var timeout = null;
function debounce() {
    if(timeout) clearTimeout(timeout);
    timeout = setTimeout(function() {
        console.log('我是a函数');
    }, 1000)
}
window.addEventListener('scroll', debounce);

// 消除全局变量timeout
function debounce(fn, delay) {
    var timeout = null;
    return function() {
        if(timeout !== null) clearTimeout(timeout);
        timeout = setTimeout(fn, delay);
    }
}
function aa(){
    console.log('我是a函数')
}
window.addEventListener('scroll', debounce(aa, 1000));

// 消除局部变量timeout
function debounce(fun, delay) {
    return function() {
        let that = this;
        clearTimeout(fun.id)
        fun.id = setTimeout(function() {
            fun.call(that)
        }, delay)
    }
} 

window.addEventListener('scroll', debounce(aa, 1000));

// es6语法 减少局部变量
function debounce(fun, delay) {
    return function() {
        clearTimeout(fun.id)
        fun.id = setTimeout(() => {fun()}, delay)
    }
} 
window.addEventListener('scroll', debounce(aa, 1000));
  • input输入触发事件的例子,增加参数传递
//模拟一段ajax请求
function ajax(content) {
  console.log('ajax request ' + content)
}

function debounce(fun, delay) {
    return function (args) {
        let that = this
        let _args = args
        clearTimeout(fun.id)
        fun.id = setTimeout(function () {
            fun.call(that, _args)
        }, delay)
    }
}
    
let inputb = document.getElementById('debounce')

// 变量赋值
let debounceAjax = debounce(ajax, 500)

inputb.addEventListener('keyup', function (e) {
    debounceAjax(e.target.value)
})

节流

  • 规定多少时间内执行一次函数
  • 常用于click,scroll事件,监听是否滑动到底部加载更多
  • 节流实现的方式有两种时间戳和定时器
// 1. 时间戳的方式  特点:第一次触发 立即执行
var throttle = function(func, delay) {
    var prev = Date.now();
    return function() {
        var that = this;
        var args = arguments;
        var now = Date.now();
        if(now - prev >= delay) {
            func.apply(that, args);
            prev = Date.now();
        }
    }
}

function aa() {
    console.log('我是aa函数');
}
window.addEventListener('scroll', throttle(aa, 1000));
// 2. 定时器方式 特点:第一次不会立即执行,最后一次会延迟执行
var throttle = function(func, delay) {
    var timer = null;
    return function() {
        var that = this;
        var args = arguments;
        if(!timer) {
            timer = setTimeout(function() {
                func.apply(that, args);
                timer = null;
            }, delay);
        }
    }
}

function aa() {
    console.log('我是aa函数');
}
window.addEventListener('scroll', throttle(aa, 1000));
// 3. 时间戳+定时器  第一次会立即执行,最后一次会延迟执行
var throttle = function(func, delay) {
    var timer = null;
    var startTime = Date.now();
    return function() {
        var curTime = Date.now();
        var remaining = delay - (curTime - startTime);
        var that = this;
        var args = arguments;
        clearTimeout(timer);
        if(remaining <= 0) {
            func.apply(that, args);
            startTime = Date.now();
        } else {
            timer = setTimeout(func, remaining);
        }
    }
}

参考

掘金-7分钟理解JS的节流、防抖及使用场景
节流

猜你喜欢

转载自www.cnblogs.com/bonly-ge/p/10102672.html