防抖节流问题

263 阅读2分钟

故事背景

面试官:‘你知道防抖节流吗?你是怎么理解的?’

我:(ps:哈哈哈哈哈哈我知道,还实现了,估计会问怎么实现了吧😄)嗯知道,blablabla

面试官:‘监听滚动事件你是选择用防抖还是节流?’

面试官:‘监听输入框的输入用防抖还是节流?’

面试官:‘移动端长列表用户疯狂下拉,用防抖还是节流?’

....

我:(ps:。。。。)。。。。

什么是防抖什么是节流

节流

节流就是规定某个时间段内只会执行一次。执行的是第一次。

防抖

防抖简单的理解就是很短时间内频繁触发时,它会很有耐心的去等到你的最后一次,这样的隐患就是在这个300ms内你啥都没看到-X- 这样就会造成卡顿....

如何真正从使用者的角度去选择呢?

  • 用户做这个动作的时候,目的是干什么?
  • 操作过程中如果使用了防抖或者节流会不会出现什么卡顿? 我们来举个🌰
  1. 滚动监听 滚动触发频率特别高,连续时间内可以一直触发,如果使用防抖,那么会一直卡着到最后,这样会造成卡顿 如果是节流,在固定时间内执行,这样相对来说不会卡顿,起码保证在一段时间内是会执行的
  2. input输入框输入 输入的时候会触发,但是我们实际上需要的就是用户输入之后的字符串就够了,不需要某个时间段拿一次,我们只关注输入完成之后的效果。所以这里考虑用防抖
  3. 长列表下拉 当用户封装下拉刷新,如果使用防抖做优化,那么可能在那段时间内用户不管下拉多少次都没有反应,这个时候就需要使用节流的方式来做,保证列表数据正常加载
  4. 屏幕resize 屏幕大小的变化过程其实不是我们需要关心的,而是变化之后需要做些什么,所以这个也是推荐使用防抖来做,这样每次执行的是最后一次的回调

PS: 以上只是我个人理解,有问题欢迎👏各位大佬提出

接下来看看你会选择防抖还是节流了吗

  • 监听滚动事件
  • 监听输入框输入
  • 长列表封装下拉
  • 屏幕resize
  • 鼠标mousemove
  • 按钮点击
  • 鼠标拖拽

其实我们还有加强版

防抖和节流综合版

在防抖的基础上加上上次触发时间间隔rest判断,如果剩余时间<=0说明要执行了,如果小于,rest之后再执行

    function lastOne(fn, delay){
        var timer = null
        var last = new Date().getTime()
        return function() {
            var now = new Date().getTime()
            var that = this
            var rest = delay - (now - last)
            var args = arguments
            clearTimeout(timer)
            if(rest > 0) {
                timer = setTimeout(()=>{
                    fn.apply(that, args)
                }, rest)
            }else{
                fn.apply(that, args)
                last = now
            }
        }
    }