在某些情况下,去抖函数会多次运行

时间:2014-10-13 18:53:09

标签: javascript marionette

我有一个看起来像的视图:

var ListItemButtonView = Backbone.Marionette.ItemView.extend({
    tagName: 'button',
    className: 'listItem-button',

    events: {
        'click': '_onClick',
        'dblclick': '_onClick'
    },

    //  Debounced to defend against accidental/spam clicking.
    _onClick: _.debounce(function () {
        if (!this.$el.hasClass('disabled')) {
            this._doOnClick();
        }

        //  Don't allow click to bubble up to the list item and cause a selection.
        return false;
    }, 100, true),

    _doOnClick: function(){
        this.model.destroy();
        console.log('Do on click has ran');
    }
});

这段代码在我当地工作正常,我没有遇到任何问题。在生产中,我看到一个错误,表明_doOnClick运行了不止一次。这对我来说没有意义,因为视图在其模型被销毁时被删除。不应该有第二个model.destroy命令。另外,我通过使用立即设置为true的函数去除函数来保护_onClick事件。从下划线的文档http://underscorejs.org/#debounce开始,它说:

  

"对于立即参数传递true以使debounce触发   前导上的函数而不是等待的后沿   间隔。在防止意外情况下很有用   双击"提交"按钮从第二次开火。"

我的实施有什么不正确可能导致一些用户设法多次运行_doOnClick吗?

编辑:

到目前为止,我唯一的预感是,如果用户的机器运行速度特别慢,那么100ms的延迟时间可能不足以清理视图。我已经增加了延迟,看看是否可以解决任何问题。

1 个答案:

答案 0 :(得分:1)

将延迟增加到1秒会使问题消失。不过,那里可能有更优雅的解决方案。

这是我的代码现在的样子。请注意,我稍微更改了结构,因为在类声明级别将函数定义为debounced而不是在实例化时导致计时器在视图的所有实例之间共享,而不是为每个实例提供单独的计时器。

var ListItemButtonView = Marionette.ItemView.extend({
    tagName: 'button',
    className: 'listItem-button',

    events: {
        'click': '_onClick',
        'dblclick': '_onDblClick'
    },

    initialize: function () {
        //  Debounced to defend against accidental/spam clicking. Bound in initialize because
        //  the debounce timer will be shared between all ListItemButtonViews if bound before initialize.
        this._debounceOnClickAction = _.debounce(this._doOnClickAction.bind(this), 1000, true);
    },

    _onClick: function () {
        this._debounceOnClickAction();
        //  Don't allow click to bubble up since handling click at this level.
        return false;
    },

    _onDblClick: function () {
        this._debounceOnClickAction();
        //  Don't allow dblClick to bubble up since handling click at this level.
        return false;
    },

    _debounceOnClickAction: null,

    _doOnClickAction: function() {
        if (!this.$el.hasClass('disabled')) {
            this.doOnClickAction();
        }
    }
});