noclist
noclist

Reputation: 1819

function call within setTimeout not executing

I am executing the function delayFilter() on keyup of an input box. I want to delay 1 second after the user stops typing and run the function filterProducts(). However, when executing filterProducts() inside of the setTimeout I get the console error "this.filterProducts is not a function". This function gets called fine when outside of the setTimeout. Why is this error being thrown?

  delayFilter() {
    let timeout = null;
    clearTimeout(timeout);

    timeout = setTimeout(function() {
      this.filterProducts();
    }, 1000);
  }

  filterProducts() {
    //do stuff
  }

Upvotes: 1

Views: 946

Answers (2)

Brenden
Brenden

Reputation: 2097

You need to bind the scope of the function in the setTimeout callback. the easiest way is to use arrow functions, if your platform supports it.

timeout = setTimeout(() => this.filterProducts(), 1000);

you can also save the scope in a variable.

var self = this;
timeout = setTimeout(funciton() { self.filterProducts() }, 1000);

Alternatively you can manually bind it. This is useful if you want to pass the function around.

timeout = setTimeout(function() {...}.bind(this), 1000);

Upvotes: 1

Athanasios Kataras
Athanasios Kataras

Reputation: 26372

That is because these, this inside the callback, does not refer to the object outside.

Try this:

delayFilter() {
    let timeout = null;
    clearTimeout(timeout);
    let self = this;
    timeout = setTimeout(function() {
      self.filterProducts();
    }, 1000);
  }

  filterProducts() {
    //do stuff
  }

You can also try the arrow function. The reason can be seen here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

An arrow function expression is a syntactically compact alternative to a regular function expression, although without its own bindings to the this, arguments, super, or new.target keywords.

delayFilter() {
    let timeout = null;
    clearTimeout(timeout);
    timeout = setTimeout(() => {
      this.filterProducts();
    }, 1000);
  }

  filterProducts() {
    //do stuff
  }

Upvotes: 3

Related Questions