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.