最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - jQuerybackbone.js - delay function call - Stack Overflow

programmeradmin6浏览0评论

I have a #search element, which when the keyup event occurs should fire a function. This function should only fire if keyup hasn't occurred in a set amount of time (say 500 milliseconds for example). This will prevent search results from updating every letter that is pressed. The problem is that with backbone.js, I have my events in a hash and the one that is applicable looks like:

'keyup #search' : 'setSearch'

which calls the setSearch() function when the keyup event occurs. I'm not really clear on how to handle it at this point. I've tried a variety of things, but nothing can maintain the timer past the function ending.

I have something like so:

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

rather than the alert('fired'), I'll have my own function run. I can see why this code doesn't work (a timer is set for every keyup event that occurs. But I still don't have a clear idea on what else I could try.

I have a #search element, which when the keyup event occurs should fire a function. This function should only fire if keyup hasn't occurred in a set amount of time (say 500 milliseconds for example). This will prevent search results from updating every letter that is pressed. The problem is that with backbone.js, I have my events in a hash and the one that is applicable looks like:

'keyup #search' : 'setSearch'

which calls the setSearch() function when the keyup event occurs. I'm not really clear on how to handle it at this point. I've tried a variety of things, but nothing can maintain the timer past the function ending.

I have something like so:

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

rather than the alert('fired'), I'll have my own function run. I can see why this code doesn't work (a timer is set for every keyup event that occurs. But I still don't have a clear idea on what else I could try.

Share Improve this question edited Jul 3, 2020 at 13:15 Brian Tompsett - 汤莱恩 5,88372 gold badges61 silver badges133 bronze badges asked Jul 20, 2011 at 2:35 MatthewMatthew 15.6k28 gold badges91 silver badges124 bronze badges
Add a comment  | 

4 Answers 4

Reset to default 18

What you are looking for is actually a function provided to you from underscore.js (a requirement of Backbone)

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

In a nutshell, this returns a new form of the anonymous function that can only be called once every 500ms. You will likely have to tweak the timing to your needs.

More Info: http://documentcloud.github.com/underscore/#throttle

You need an instance variable in your view that stores the timer ID, then you can stop it and restart it as needed:

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

So, if the timer is already running, you call clearTimeout to stop it, start a new timer, and store the timer ID in self.timer (AKA this.timer). You'll also want to reset the stored timer ID in the timer's callback function or your setSearch won't do anything after its timer has fired once. And all the self business is just to capture this for use in the timer's callback function.

Preventing the updating of search results on every keyup is exactly the kind of situation that Underscore's _.debounce(function, wait) function is meant to deal with. The underscore documentation for _.debounce() states:

Creates and returns a new debounced version of the passed function which will postpone its execution until after wait milliseconds have elapsed since the last time it was invoked. Useful for implementing behavior that should only happen after the input has stopped arriving.

Your refactored code would look as simple as:

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

Since you want your event handler events to be able to maintain whether or not an event has recentlyFired, you probably want to wrap your handler into a closure and maintain that status. The status should be changed to true when an event has fired, and reset to false after a delay of 500ms.

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);
        }
    }
}( );
发布评论

评论列表(0)

  1. 暂无评论