Sarus
Sarus

Reputation: 3313

Ember.js: Unexpected Ember.run.debounce behavior with observor ... fires multiple times after debounce period elapses

I'm having some difficulty with using Ember.run.debounce. I'll be the first to admit that I'm probably misunderstanding how debounce is supposed to be used.

My Problem:

I have an input text box and I want to construct a regular expression based on the text in the input box. I setup an observer on the input helpers value field but this observor fires everytime the input changes. What I really want is to only build the regexp if the user has stopped typing for X amount of time.

So here's what the observer looks like:

  inputTextObservor: function(){
      //Build Regular Expression and do other logic
  }.observes('inputText')

What I thought would work:

I thought I could wrap my regexp creation logic in the observor with Ember.run.debounce and that this would prevent the regexp from being created while the user was typing.

  inputTextObservor: function(){
    Ember.run.debounce(this, function(){
      // Build Regular Expression and do other logic
      // should only be called if the user stops typing 
      // for 2000 milliseconds
    }, 2000)
  }.observes('inputText')

What actually happens:

Using the setup above, the regexp creation logic inside debounce doesn't execute for 2000 milliseconds (as set in the debounce call) but then executes once for everytime the observer was fired. So for example, if the debounce time is 2000 milliseconds, and the user is typing "HelloWorldOfEmber", but they type 1 character every 1000 milliseconds (i.e., pretty slowly), I would expect that the debounce method is called once 2000 milliseconds after the user finishes typing "HelloWorldOfEmber".

What actually happens is that after 2000 milliseconds, the debounce call is executed and from there on out is executed for every time the user typed a character.

I recreated my setup with a very simple jsbin. The debounce time in the jsbin is set to 2000 milliseconds. If you type into the input field you'll notice that after 2000 milliseconds the debounced function is fired once for every character you typed.

http://jsbin.com/gagocufofavi/1/edit?html,css,js,output

Questions:

I thought that debounce was typically used to prevent a function from firing until the event triggering the function stops occurring (within a set time window), and that it should only fire once.

  1. Is my understanding of Debounce completely off?
  2. Is my code completely wrong?
  3. How can I achieve the desired behavior?

I'm using the following versions:

DEBUG: ------------------------------- ember.js:3911
DEBUG: Ember      : 1.6.1 ember.js:3911
DEBUG: Handlebars : 1.3.0 ember.js:3911
DEBUG: jQuery     : 1.10.2 ember.js:3911
DEBUG: ------------------------------- 

Thank you!

Upvotes: 2

Views: 923

Answers (1)

blessanm86
blessanm86

Reputation: 31779

The debounce method will check to see if the passed function is the same as the one sent before. It uses a '===' check on the previous method sent and the current method sent.

Here is the relevant line that does the check.

Here is the working demo.

Create a function and assign it to variable and pass that variable to the debounce method.

App.IndexController = Ember.Controller.extend({
  events: Ember.A(),

  createRegExp: function() {
    console.info(this.get('inputText'));
    this.get('events').pushObject(this.get('inputText'));
  },

  inputTextObservor: function(){
    Ember.run.debounce(this, this.createRegExp, 2000);
  }.observes('inputText')
});

Upvotes: 5

Related Questions