Debounced and Throttled Observers in Ember.js

Often in complex ember apps you want to use debouncing and throttling, to avoid doing expensive processing or too many server requests. I had hacked together a solution for this with underscore, but then I found out that Ember.js includes built in throttle and debounce functions. A few minutes later, I came up with these handy little helpers:

Ember.debouncedObserver = function(func, key, time) {  
    return Em.observer(function() {
        Em.run.debounce(this, func, time);
    }, key)
};

Ember.throttledObserver = function(func, key, time) {  
    return Em.observer(function() {
        Em.run.throttle(this, func, time);
    }, key)
};

Using them is easy, just wrap your observer function with them like this:

App.IndexController = Em.ArrayController.extend({  
    selectObserver: Ember.debouncedObserver(function() {
        this.set('debounceSelected', this.get('selectedValue.firstName'));
    }, 'selectedValue', 1000),

    selectObserver2: Ember.throttledObserver(function() {
        this.set('throttleSelected', this.get('selectedValue.firstName'));
    }, 'selectedValue', 1000)

});

If you are using coffeescript, these have a slightly nicer argument order and support multiple dependant keys:

Ember.debouncedObserver = (keys..., time, func) ->  
  Em.observer ->
    Em.run.debounce @, func, time
  , keys...

Ember.throttledObserver = (keys..., time, func) ->  
  Em.observer ->
    Em.run.throttle @, func, time
  , keys...

You need to decide whether throttling or debouncing is right for you. Ben Alman has a good blog post that goes into more detail.

Here's a JSFiddle showing the code in action.

Alex Speller

Full stack hacker and entrepreneur working on my own projects including emberkit.com, an Ember.js SaaS kit. You can usually find me in #emberjs on freenode dishing out advice and solving problems.

  • London