millermedeiros/js-signals

add some easy way to bind Signal.dispatch()

Closed this issue · 4 comments

one thing that I always have to do is to make sure Signal.dispatch() is called on the right context, specially when it needs to be called on a callback, eg:

$('#foo').fadeOut(500, ended.dispatch); // won't work!

The case above doesn't work because this inside dispose() points to the wrong object (jQuery calls the callback passing the element as this). A solution is to create another function that is bound to the proper context:

// works
$('#bar').fadeOut(500, dispatchEnded);

function dispatchEnded(){
  ended.dispatch();
}

The main reason why I didn't auto bind the dispatch() context is because I was unsure if it would make it harder to subclass another signal, but we can simply reuse the method of the prototype like this:

function Signal(){
  var self = this;
  this.dispatch = function(){
    Signal.prototype.dispatch.apply(self, arguments);
  };
  // ...
}

If the user can instantiate a Signal he can also access the Signal.prototype which is enough to grab the unbound method and reuse it (like CompoundSignal does).

Overall I think it will avoid more problems than it will cause, specially since most people don't understand how scope works in JS and the advanced users will know a way around it (call the prototype method directly).

Another solution is to add a new method to the dispatch() function that does the binding:

function Signal(){
  var self = this;
  this.dispatch.bind = function(){
    return function(){
      self.dispatch.apply(self, arguments);
    };
  };
  // ...
}

Which would be used like this:

$('#foo').fadeOut( 500, ended.dispatch.bind() );

I like the automagical approach better - calling bind() without any argument fells weird and user might not know he needs to do that.

If you're using signals, you really ought to understand scope. That said, I'm down.

this shipped on v0.9.0

"since most people don't understand how scope works in JS" I understand your point but that's their problem. Additionally the change is not consistent - why not autobind other methods like halt, forget? They can also be used as callbacks.

IMHO autobinding for dispatch should be removed.