Multiple Callbacks in CoffeeScript

2019-08-10 22:46发布

I am trying to work out the correct behavior to string multiple callbacks together.

class Person

  move_head: ->
     head.animate({
        left: x,
     },{
        complete: @move_foot,
     });

  move_foot: ->
     foot.animate({
        left: x,
     },{
        complete: @move_arm,
     });

  move_arm: ->
     arm.animate({
        left: x,
     },{
        complete: something_else,
     });

Now the issue is, head animates fine which calls foot. Foot also animates fine. The problem is that when foot is done, it does not animate the arm. I can't figure out what the problem could be. I have a guess though that it might have to do with a scoping issue.

1条回答
老娘就宠你
2楼-- · 2019-08-10 23:24

Use the fat arrow =>, to bind this to current context:

move_head: =>
  // ...
move_foot: =>
  // ...
move_arm: =>
  // ...

UPDATE: Here's a short explanation:

One of the biggest gotchas in javascript is this. In a method (such as your move_head), this is your instance of Person, if you call it as new Person().move_head(). But it doesn't have to be. For instance, if you call it using new Person().move_head.call(null), this will be null.

But the biggest gotcha is that when you are inside a function, like a complete callback to a jQuery animate call, this is no longer bound to your object! It is probably bound to window, but not for certain. So what happens in your case is that you give jQuery a reference to @move_foot (or really, this.move_foot). This call seems to work, in that your animation completes. But when jQuery calls that function, it will no longer know that this is supposed to be your Person. So when you tell it to then go to @move_arm, it will look for a method move_arm on some other object (perhaps window).

A common way to solve this is to save a reference to this before you make the call, like var self = this, and then, inside the callback, refer to that bound variable self instead.

You could use this technique, there is nothing wrong with it. Something like:

move_head: ->
  self = this
  head.animate(..., complete: self.move_foot)

But CS does this (binding of this) for you, by giving you the fat arrow: =>.

The fat arrow says: "Everything inside this method referring to this, shall refer to this object."

查看更多
登录 后发表回答