js 防抖函数执行问题

问题是:每次连续点击都会执行 opengeme2 函数

期望:每次连续点击只执行最后一次~

希望大佬们指点一下
  • code
js
toPlay(i,status){
    var send = () => {
        var item = this.listData[i];
        console.log(item,this.listData,'itemlistData',i)
        if(loginData && item.swHref != '' && loginData.isDemo == 1){
            return opengeme2( 5 , item.platformName ,  item.platformId ,  item.isQuota ,  item.swHref )
        }else{
            return opengeme2( 5 ,  item.platformName ,  item.platformId ,  item.isQuota ,  item.swHref )
        }
    }
    if(status==2){
        if(this.flagd){
            let _this = this;
            setTimeout(_this.debounce(send, 500), 21);
            console.log("status",22222222)
        }
    }else{
        let _this = this;
        setTimeout(_this.debounce(send, 500), 21);
        console.log("dooooo",i,'n')
    }
    this.flagd = false;
},
debounce(fn, wait) {
    var timer = null;
    return function () {
        var context = this;
        var args = arguments;
        if (timer) {
            clearTimeout(timer);
            timer = null;
        }
        timer = setTimeout(function () {
            fn.apply(context, args);
        }, wait);
    };
},
vue
<div class="play" @click="toPlay(i)">
     <p>进入页面</p>
     <div class="bgdir"></div>
</div>
阅读 2.8k
3 个回答
function debounce(fn, wait) {
    var timer = null;
    return function () {
        var context = this;
        var args = arguments;
        if (timer) {
            clearTimeout(timer);
            timer = null;
        }
        timer = setTimeout(function () {
            fn.apply(context, args);
        }, wait);
    };
}

// .....
toPlay: debounce(function(i,status){
    var send = () => {
        var item = this.listData[i];
        console.log(item,this.listData,'itemlistData',i)
        if(loginData && item.swHref != '' && loginData.isDemo == 1){
            return opengeme2( 5 , item.platformName ,  item.platformId ,  item.isQuota ,  item.swHref )
        }else{
            return opengeme2( 5 ,  item.platformName ,  item.platformId ,  item.isQuota ,  item.swHref )
        }
    }
    if(status==2){
        if(this.flagd){
            send()
        }
    }else{
        send()
    }
    this.flagd = false;
})

lodash 的 debounce 函数推荐给你

问题根源是你 每次调用 debounce 都会生成一个 timer,这些 timer 是相互独立的,后面的调用不会取消前面的定时
所以写 debounce 有两种方案。
第一种是将 debounce 写成高阶函数,把需要防抖的函数包装一遍再使用,如楼上 @zangeci 的方法;
第二种则是用闭包维持 timer ,确保每一次调用都能访问同一个 timer 变量:

const debounce = (() => {
    let timer = null;
    return (fn, duration) => function(...args){
        if(typeof timer === 'number') clearTimeout(timer);
        timer = setTimeout(() => {
            fn(...args);
            timer = null;
        }, duration);
    }
})();

// 调用的时候
debounce(toPlay, 200)(args);  // args 为传递给 toPlay 的参数

(还有一种是在外部维护一个 timer 变量,但这种写法很矬,不推荐也无需介绍。)
其实三种方法原理都一样,推荐使用 高阶函数,这样可以复用 debounce 函数。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题