clearTimeout 包裹在闭包中时?

clearTimeout when wrapped in closure?

已更新

HTML

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

JS - 使用 KnockoutJS 创建一个可观察的 'notification' 消息数组。

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>'
});

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

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

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

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

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

然后 timerId 在传递给 setTimeout (a.k.a."a closure") 的匿名函数的函数范围内,它和 data 都可以看到。

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

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