Comments on: jQuery EventEmitter https://j11y.io/javascript/jquery-eventemitter/ Sun, 22 Mar 2015 15:39:22 +0000 hourly 1 https://wordpress.org/?v=5.0.13 By: Rich https://j11y.io/javascript/jquery-eventemitter/#comment-2417 Wed, 17 Oct 2012 08:53:14 +0000 https://j11y.io/?p=2063#comment-2417 Recently I used a similar approach of using jQuery events, until I was faced with a rather peculiar bug in my app. When you trigger events on the object instance, jquery will also execute methods of that object which it thinks are event handlers.

What would you expect to happen in the following code:

var obj = {
  method: function() {
    alert('method 1 executed');
  },
  onmethod: function() {
    alert('method 2 executed');
  }
};
 
$(obj).on('method.namespace', function() {
  alert('handler executed');
});
 
$(obj).trigger('method.namespace');

Here’s a link to run that code: http://jsbin.com/amaxes/1

This behaviour was unexpected for me and caused quite a serious bug in my application. I have since decided it’s a bad idea to use jQuery events for non-dom objects.

]]>
By: James https://j11y.io/javascript/jquery-eventemitter/#comment-2416 Wed, 11 Apr 2012 10:04:59 +0000 https://j11y.io/?p=2063#comment-2416 @Esailija, good points! I guess I didn’t think enough about the implications of using jQ.

]]>
By: Esailija https://j11y.io/javascript/jquery-eventemitter/#comment-2415 Tue, 10 Apr 2012 16:34:02 +0000 https://j11y.io/?p=2063#comment-2415

What event system can avoid this?

For custom events that don’t require the jQuery custom event features (bubbling, preventdefault, delegation, namespaces etc);

function Observable() {
    this.listeners = [];
}
 
Observable.prototype = {
 
    constructor: Observable,
 
    observe: function( fn ) {
        this.listeners.push( fn );
    },
 
    unobserve: function( fn ) {
        var index;
 
        index = this.listeners.indexOf( fn );
 
        if( index > -1 ) {
            this.listeners.splice( index, 1 );
        }
 
    },
 
    update: function() {
        var listeners = this.listeners,
            len = listeners.length,
            i;
 
 
        for( i = 0; i < len; ++i ) {
            listeners[i].apply( null, arguments );
        }
 
    }
};
 
function App() {
  this.someEventHappened = new Observable;
  this.someOtherEventHappened = new Observable;
}
 
var myApp = new App();
 
myApp.someEventHappened.observe( function() {
    alert( "someEvent" );
});
 
myApp.someEventHappened.update(); //Should normally happen inside of the object

Now when the object goes out of scope, so do the event listeners. It also
has the added benefit of not being stringly typed.

]]>
By: James https://j11y.io/javascript/jquery-eventemitter/#comment-2414 Tue, 10 Apr 2012 16:11:03 +0000 https://j11y.io/?p=2063#comment-2414 @Esailija, it can be confusing yes. I do prefer a holistic API (direct methods instead of re-wrapping with jQ every time) though. I guess `removeData` is optional. You could implement your own “destroy” method. What event system can avoid this?

]]>
By: Esailija https://j11y.io/javascript/jquery-eventemitter/#comment-2413 Tue, 10 Apr 2012 16:00:29 +0000 https://j11y.io/?p=2063#comment-2413 Not wrapping it in a jQuery yet requiring the use of jQuery.removeData on the object is probably more confusing.

]]>
By: James https://j11y.io/javascript/jquery-eventemitter/#comment-2412 Tue, 10 Apr 2012 15:31:45 +0000 https://j11y.io/?p=2063#comment-2412 @Esailija, it provides the convenience of not having to confusingly wrap myApp in a jQuery call.

]]>
By: Esailija https://j11y.io/javascript/jquery-eventemitter/#comment-2411 Tue, 10 Apr 2012 15:23:02 +0000 https://j11y.io/?p=2063#comment-2411 Because it’s not actually doing anything, just giving different names to the methods. You can just directly use the jQuery methods with their original names:

$(myApp).on('someEvent', function() {
  alert('someEvent!');
})
 
$(myApp).trigger('someEvent');
]]>
By: James https://j11y.io/javascript/jquery-eventemitter/#comment-2410 Tue, 10 Apr 2012 14:47:11 +0000 https://j11y.io/?p=2063#comment-2410 @Esailija, nice work! Why did you say it was useless? I actually find it quite useful.

]]>
By: Esailija https://j11y.io/javascript/jquery-eventemitter/#comment-2409 Tue, 10 Apr 2012 14:29:59 +0000 https://j11y.io/?p=2063#comment-2409 You could reduce this code to:

(function($) {
 
    function makeProxy( name ) {
        return function() {
            ( this._JQ || ( this._JQ = $( this ) ) )[name].apply( this._JQ, arguments );
        };
    }
 
    $.eventEmitter = {
        emit: makeProxy( "trigger" ),
        once: makeProxy( "one" ),
        on: makeProxy( "on" ),
        off: makeProxy( "off" )
    };
 
}(jQuery));

The uselessness in all of this is now more evident.

]]>
By: James https://j11y.io/javascript/jquery-eventemitter/#comment-2408 Sat, 07 Apr 2012 13:14:02 +0000 https://j11y.io/?p=2063#comment-2408 @Dave, Ah, thanks, I forgot to remove that. I think it’s best without. As you said, it would mean more confusion with unbinding.

]]>