【问题标题】:clearTimeout when wrapped in closure?包裹在闭包中时的clearTimeout?
【发布时间】:2015-09-05 06:29:08
【问题描述】:

更新

HTML

<div class="notification-container" data-bind="foreach: notificationArray">
     <notification params="data: $data"></notification>
</div>

JS - 使用 KnockoutJS 创建一个可观察的“通知”消息数组。

appViewModel.notificationArray = ko.observableArray([
    { message : 'Test 1' },
    { message : 'test 2' }
]);

使用 Knockout 创建通知组件

ko.components.register('notification', {
    viewModel: function(params) {
        var data = params.data;

        /* set the message to the data.message */
        this.message = data.message || null;

        /* removes the notification from the array */
        this.removeNotification = function() {
            appViewModel.notificationArray.remove(data);
        };

        /* create timer to remove notification after 5s */
        /* need to wrap in closure so that inside of the setTimeout it can know about the data object needed to send to the remove() command */
        this.timer = function(obj, timeoutLength) {
            /* adding return statement per suggestion on Stack Overflow */
            return setTimeout(function() {
                appViewModel.notificationArray.remove(obj);
            }, timeoutLength);
        };

        this.timer(data, 5000);

       /* log will output function structure */
       /* clearTimeout will not work */
        this.hover = function() {
            console.log(this.timer);
            clearTimeout(this.timer);
        }

    },
    template: '<div class="notification show-notification" data-bind="event: { mouseover: hover, fastClick: hover }">'
        +'<div class="notifications-close clickable right" data-bind="fastClick: removeNotification"><span class="icon icon-x"></span></div>'
        +'<div class="notification-text" data-bind="text: message"></div>'
        +'</div>'
});

更新以反映有效的解决方案

JS

appViewModel.notificationArray = ko.observableArray([
    { message : 'Test 1' },
    { message : 'test 2' }
]);


ko.components.register('notification', {
    viewModel: function(params) {

        var data = params.data;

        this.message = data.message || null;
        this.timer = null;

        this.removeNotification = function() {
            appViewModel.notificationArray.remove(data);
        };

        this.timer =  ( function(self) {
            return setTimeout(function() {
                self.removeNotification();
            }, 5000);
        })(this);

        this.hover = function () {
            clearTimeout(this.timer);
        };

        this.restart = function() {
            this.timer = ( function(self) {
                return setTimeout(function() {
                    self.removeNotification();
                }, 5000);
            })(this);
        }

    },
    template: '<div class="notification show-notification" data-bind="event: { mouseover: hover, fastClick: hover, mouseout: restart }">'
        +'<div class="notifications-close clickable right" data-bind="fastClick: removeNotification"><span class="icon icon-x"></span></div>'
        +'<div class="notification-text" data-bind="text: message"></div>'
        +'</div>'
});

【问题讨论】:

  • 你在哪里附加悬停处理程序?

标签: javascript closures


【解决方案1】:

您没有将this.timer 设置为setTimeout 的结果。也许你需要return setTimeout

现在解决您的第二个问题。 this.hoverthis 一起调用。这已在许多其他问题中得到解决。一种方法是在正确的范围内使用var self = this 以获得正确的this,或者我当前的偏好是this.hover = function() {...}.bind(this);

【讨论】:

  • 除非您的用例比示例更复杂,否则关闭确实没有任何意义,您可以使用this.timer = setTimeout(...)
  • @Daniel 我已经更新了我的 OP 以反映您的建议。我可能实施错了,但实际上它的功能并没有比以前更好。
  • @DanielA.White 谢谢,我在我的 OP 中添加了一个部分,显示最终的工作代码。你能解释一下为什么会这样吗:this.timer = (function(self){return setTimeout(function(){self.removeNotification();},5000);})(this);不同于: this.timer = function(self) { return setTimeout(function() { self.removeNotification(); }, 5000); }; this.timer(this);
【解决方案2】:

编辑:此答案在发布接受的答案之前开始。确定的问题相似,但解决方案略有不同。

1) 您可以将整个this.timer = 语句替换为

var timerId =  setTimeout(function(){
    appViewModel.notificationArray.remove(data), 5000);
    timerId = 0;  // timer finished
};

然后 timerId 在传递给 setTimeout(又名“闭包”)的匿名函数的函数范围内,它和 data 都可以看到。

2) 悬停功能也可以使用闭包。

this.hover = function() {
    console.log("timer " + timerId ? timerId : "finished");
    if( timerId)
        clearTimeout(timerId); 
}

【讨论】:

    猜你喜欢
    • 2014-02-12
    • 1970-01-01
    • 2014-07-30
    • 1970-01-01
    • 1970-01-01
    • 2018-09-19
    • 1970-01-01
    • 1970-01-01
    • 2018-06-02
    相关资源
    最近更新 更多