Jacob
Jacob

Reputation: 93

Coffeescript setInterval in class

I started writing coffeescript last week, as I am programming a new Play20 site where coffeescript is the standard. I want to update a getData function in my class every 5 minutes, but the setInterval function does not bind to my class. Only the first time it calls getData, because the 'this' object is still reachable, as the setUpdateInterval() function is called from within the constructor.

But after the first call, the setInterval does not have any connection anymore with the Widget instance, and does not know what the this.getData() function is (and how to reach it).

Does someone know how to do it?

Here is my code:

class Widget
  constructor: (@name) ->
    this.setUpdateInterval()

  getData: ->
    console.log "get Data by Ajax"

  setUpdateInterval: (widget) ->
    setInterval( this.getData(), 3000000 )

Upvotes: 3

Views: 4009

Answers (3)

Philip Orange
Philip Orange

Reputation: 53

This is handy in node as well. It's a varient of Tass's answer.

class Widget
  constructor: (@options = {}) ->
    @options.interval ?= 1000
    @setInterval()

  timer: ->
    console.log 'do something'

  setInterval: ->
    cb = @timer.bind @
    setInterval cb, @options.interval

w = new Widget()

Upvotes: 0

Reactormonk
Reactormonk

Reputation: 21740

Now here some Javascript magic is required. Reference

class Widget
  constructor: (@name) ->
    this.setUpdateInterval()

  getData: ->
    console.log "get Data by Ajax"

  setUpdateInterval: (widget) ->
    callback = @getData.bind(this)
    setInterval( callback, 3000000 )

This will work in almost all browsers (guess which one not), so the function will have to be bound differently. Some coffeescript magic:

callback = => @getData

Upvotes: 7

hvgotcodes
hvgotcodes

Reputation: 120318

The problem is that you are executing the function, instead of passing a reference to it.

Now, it sounds like you need to also keep the scope of the instance. do and => can help with that.

 setUpdateInterval: (widget) ->
    setInterval (do =>
      @getData), 3000000
    true

compiles to

Widget.prototype.setUpdateInterval = function(widget) {
      var _this = this;
      setInterval((function() {
        return _this.getData;
      })(), 3000000);
      return true;
    };

you will note the code executes a self invoking function, which return a function, that creates a closure around this, locking it into the scope of the callback (as _this)

Also note that you don't need to pass widget to the method (you aren't using it anywhere), and you would invoke this function in your constructor, to set up the interval. Whatever you do, you only want to call this method once. You could just put the contents of the function in your constructor.

Finally, since coffeescript returns the value of the last statement from all functions, I throw a true in there, but that might no be necessary.

Upvotes: 3

Related Questions