包裹在封闭中的clearTimeout?

时间:2015-09-04 20:40:35

标签: javascript closures

更新

HTML

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

JS - 使用KnockoutJS创建一个可观察的通知数组&#39;消息。

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

2 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:0)

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

1)您可以用

替换整个this.timer =语句
var timerId =  setTimeout(function(){
    appViewModel.notificationArray.remove(data), 5000);
    timerId = 0;  // timer finished
};

然后timerId在传递给setTimeout的自主函数的函数范围内(a.k.a。&#34;一个闭包&#34;),其中和data都可以看到。

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

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