shared debounce 共享防抖动

76 阅读2分钟

防抖动不是什么新鲜事,相信很多切图仔都写过。

function debounce(fn, delay = 300) {
    let timer;
    return function() {
        if (timer) {
            clearTimeout(timer);
            timer = setTimeout(() => {
                fn();
            }, delay);
        }
    }
}

// 比如我有一个button, 点击会触发btn_click()
btn_click() {
    function doClick() {
        // 我想执行的代码
    }
    debounce(doClick, 300)();
}

原理很简单,当user 300ms 以内第二次点击button的时候,会先把前一次的点击事件干掉,缓存第二次,重新计时300ms,如果第二个300ms 以内有再次点击,也会把前一次点击干掉,一直到超出300ms 为止,才执行doClick。


最近做了一个相当可怕的requirement,

1.png

  1. 允许user 输入input1
  2. user 点击btn1,set value to input1
  3. user 点击btn2,set value to input1
  4. user 点击btn3,如果input1原本非空,do nothing; 如果input1为空,set default value to input1
  5. user 点击btn4,如果user从来没有input 过input1,set input1 为空, 否则, keep input1 value。 hide input1, show input2
  6. 有一段nextTick 不断auto set value to input1
  7. btn1, btn2, btn3, btn4, input1.blur, auto refresh 除了set value to input1,还有一堆async functions 如果user 依次触发以上2345,你想象中的执行顺序是: btn1_click(), btn1_async1(), btn1_async2(), btn2_click(), btn2_async1(), ... 但实际上是, 执行btn1_click(), btn1_async1 入异步队列, btn1_async2 入异步队列, 执行btn2_click(), btn2_async1 入异步队列, ... , 执行btn1_async1(), 执行btn1_async2(), 执行btn2_async1(), ... 可想而知,如果user 无序快速click 这4个button,叠加auto refresh,最后input1里面是个什么鬼value,那只有鬼才知道了。 为了可控,我们试着引入debounce,并且让这4个button的click, input.blur,auto refresh 共享timer。我给它起了个名字叫shared debounce
function sharedDebounce(fn, delay = 300) {
    return function() {
        const that = this;
        if (that.timer) {
            clearTimeout(that.timer);            
        }
        that.timer = setTimeout(() => {
            fn();
            clearTimeout(that.timer);
        }, delay);
    }
}
// 前端用vue写的
data() {
    return {
        timer: null
    };
}
methods: {
    btn1_click() {
        function proceed() {
            this.input1Value = '111';
            this.btn1_async1();
            this.btn1_async2();
        }
        sharedDebounce(proceed.bind(this), 300).apply(this);
    }
    
    btn2_click() {
        function proceed() {
            this.input1Value = '222';
            this.btn2_async1();
        }
        sharedDebounce(proceed.bind(this), 300).apply(this);
    }
    
}

如此,给所有button 和auto refresh 都加上shareDebounce。当user 无序快速click 这4个button,程序只会响应最后一个事件。

(原创文章,转载请注明出处)