Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Coffeescript timer and 'this' pointer on callback

Tags:

coffeescript

I'm having a problem with what the browser considers 'this' to be. In the following example, calling pingMe() on abc will wait 1 second and then the browser will say that Object DOMWindow has no method 'func'. Instead of resolving 'this' to the instance of class ABC (abc), it instead resolves to the DOMWindow, as if the object wasn't involved. I'm clearly not understanding how setTimeout works with respect to callback scope. Any suggestions how i can make this callback succeed?

class ABC
  @func = null

  constructor: (func) ->
    @func = func

  pingMe: ->
    setTimeout(doPing, 1000)

  doPing = ->
    @func()

abc = new ABC ->
  alert "HI"
abc.pingMe()
like image 604
Larry Avatar asked Feb 07 '11 01:02

Larry


2 Answers

I got this code working.

class ABC
  @func = null

  constructor: (func) ->
    @func = func

  pingMe: ->
    setTimeout =>
     @doPing()
    , 1000

  doPing: ->
    @func()

abc = new ABC ->
  alert "HI"
abc.pingMe()

Your doPing method was defined doPing = ->, whereas the others all use name: ->, I changed it that way. pingMe uses => to create a unnamed function, and @doPing to bind this to the function.

Not sure if this is correct, I rarely use JavaScript. But I hope it might give you a direction to look further.

like image 94
Reiner Gerecke Avatar answered Nov 20 '22 07:11

Reiner Gerecke


An alternative solution which is closer to what you would do in ES5 is:

pingMe: ->
    setTimeout(@doPing.bind(@), 1000)

or if you want to save on parentheses:

pingMe: ->
    setTimeout (@doPing.bind @), 1000

Note that bind is ES5, so only available in IE from version 9.


Also note, you should at all costs avoid the temptation to try:

    setTimeout(@doPing.bind @, 1000)    # BAD!
       or
    setTimeout @doPing.bind @, 1000     # BAD!

because both of those pass the number as the second argument to bind, not setTimeout!

like image 40
joeytwiddle Avatar answered Nov 20 '22 07:11

joeytwiddle