Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone: throttle a collection filter event on a View

In my app I have a view displayed as a table which contains a collection fetched from the server. I want the user to be able to filter this collection writing a search string in a text box.

Problem is that the keyup event fire for every keystroke, and I want to avoid this to not overload the server with useless requests. So I thought to use the underscore's throttle function but I can't implement it in a working way.

events: {
    'keyup #filter' : 'filter_collection'
}

filter_collection: function(e) {
    var el, throttled, value;

    el = e.currentTarget;
    value = $(el).val();
    this.collection.server_api.filter = value;
    throttled = _.throttle(_.bind(this.update_collection, this), 5000);
    throttled();
}

update_collection: function() {
    var promise, self;

    self = this;
    promise = this.collection.fetch();
    $.when(promise).then(function() {
      self.collection.pager();
    });
}

In this way the update_collection function is called for every keystroke, as it was before without throttle. I tried also with debounce but all the requests will simply fire after the waiting time. What I'm missing?

Any help is appreciated, thank!

like image 860
Ingro Avatar asked Dec 15 '22 12:12

Ingro


1 Answers

The function called each time a keyup event occurs is filter_collection which is not itself throttled, the one you create inside is immediately called and discarded.

You should bind your event to a throttled function:

var V = Backbone.View.extend({
    events: {
        'keyup #filter' : 'filter_collection'
    },

    filter_collection: _.throttle(function(e) {
        var el, throttled, value;

        el = e.currentTarget;
        value = $(el).val();

        this.update_collection(value);
    }, 5000),

    update_collection: function(val) {
        var promise, self;
        self = this;
        promise = this.collection.fetch();
        $.when(promise).then(function() {
          console.log('fetched '+val);
        });
    }
});

You could of course use _.debounce if you prefer. And see http://jsfiddle.net/nikoshr/zWrgW/ for a demo

like image 168
nikoshr Avatar answered Jan 07 '23 01:01

nikoshr