jquery / backbone.js - 延迟函数调用

时间:2011-07-20 02:35:44

标签: javascript jquery javascript-events backbone.js settimeout

我有一个#search元素,当keyup事件发生时应触发一个函数。只有在设定的时间内没有发生keyup时才会触发此功能(例如500毫秒)。这将阻止搜索结果更新每个按下的字母。问题是使用backbone.js,我将事件放在哈希中,并且适用的事件如下:

'keyup #search' : 'setSearch'

setSearch()事件发生时调用keyup函数。我现在还不清楚如何处理它。我尝试过各种各样的东西,但没有任何东西可以让计时器超过功能结束。

我有类似的东西:

setSearch: function(event) {
            var timer = window.setTimeout( function() {
                // run function here
                alert('fired');
            }, 500);
    },

而不是alert('fired'),我将运行自己的函数。我可以看到为什么这段代码不起作用(为发生的每个keyup事件设置了一个计时器。但我仍然不清楚我还能尝试什么。

4 个答案:

答案 0 :(得分:19)

您正在寻找的实际上是一个从underscore.js(Backbone的要求)提供给您的功能

 setSearch: _.throttle(function() {
                //Do Stuff
              }, 500),

简而言之,这将返回一种新形式的匿名函数,每500ms只能调用一次。您可能需要根据需要调整时间。

更多信息: http://documentcloud.github.com/underscore/#throttle

答案 1 :(得分:3)

您需要在视图中存储一个存储计时器ID的实例变量,然后您可以根据需要将其停止并重新启动:

setSearch: function(event) {
    var self = this;
    if(self.timer)
        clearTimeout(self.timer);
    self.timer = setTimeout(function() {
        alert('fired');
        self.timer = null;
    }, 500);
}

因此,如果计时器已在运行,则调用clearTimeout将其停止,启动新计时器,并将计时器ID存储在self.timer(AKA this.timer)中。您还需要在计时器的回调函数中重置存储的计时器ID,否则setSearch在计时器触发一次后将不会执行任何操作。所有self业务只是捕获this以便在计时器的回调函数中使用。

答案 2 :(得分:1)

防止每个keyup更新搜索结果正是Underscore _.debounce(function, wait)函数要处理的情况。 underscore documentation for _.debounce()州:

  

创建并返回传递的function的新去抖版本,该版本将推迟执行,直到自上次调用后经过wait毫秒。用于实现仅在输入停止到达后才会发生的行为。

您重构的代码看起来很简单:

setSearch: function(event) {
    _.debounce(doSomething, 300);
},

答案 3 :(得分:0)

由于您希望事件处理程序事件能够维护事件是否具有recentlyFired,因此您可能希望将处理程序包装到闭包中并保持该状态。事件触发后状态应更改为true,并在延迟500ms后重置为false。

setSearch: function( ) {
    var firedRecently = false;
    return function(event) {
        if (firedRecently) {
            // it has fired recently. Do you want to do something here?
        } else {
            // not fired recently
            firedRecently = true;
            // run your function here
            alert('fired');
            var resetStatus = window.setTimeout( function () {
                firedRecently = false;
            }, 500);
        }
    }
}( );