marko-js-archive / marko-widgets

[LEGACY] Module to support binding of behavior to rendered UI components rendered on the server or client
http://v3.markojs.com/docs/marko-widgets/
MIT License
141 stars 40 forks source link

10 stateful widgets in a page is emmiting Emitter memory leak error #87

Closed vl-ing closed 9 years ago

vl-ing commented 9 years ago

When I add anything more than 10 stateful widgets in a page, the destroy is queuing up more 10 listeners and is throwing the following error

(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.EventEmitter.addListener 
patrick-steele-idem commented 9 years ago

Hi @vidya-lingineni, which version of marko-widgets are you using?

vl-ing commented 9 years ago

4.3.2

patrick-steele-idem commented 9 years ago

How are you attaching event listeners?:

If you use this.subscribeTo() then the event listeners will automatically be unsubscribed when either the source or target is destroyed. I recommend using declarative event binding because there are no event listeners attached at runtime (it uses event delegation based on event bubbling).

Also, if it is easy, I strongly recommend upgrading to the latest marko-widgets:

npm install marko-widgets@^5.0.0-beta --save
vl-ing commented 9 years ago

we are using this.subscribeTo(someOtherEventEmitter).on('foo')

All of the listeners are raptor pubsub emitters in my case

patrick-steele-idem commented 9 years ago

I think I will need to take a closer look at your app to understand why you are seeing event emitter leaks. Without looking at the code it is hard to say if the problem is in your app or in marko-widgets.

Have you tried npm install marko-widgets@^5.0.0-beta --save ?

maberer commented 9 years ago

@vidya-lingineni for what it's worth: I think you should really use declarative event binding for most of the parts within your app - thats what @patrick-steele-idem recommends. With that, you will profit from marko-widgets phenomenal event bubbling... your app won't slow down even with a huge number of "bindings"...

Personally, I use this.subscribeTo() only in the rare case of application wide events. These events are typically "off strict DOM-hierarchy"... and you most probably do not need many of them...

We created a nice FAQ entry about this topic some time back. Please See https://github.com/marko-js/marko-widgets/blob/master/docs/faq.md#how-do-widgets-communicate

Please check it out and tell us, if that is OK for you...

vl-ing commented 9 years ago

Thanks both of you for the reply.

We are wrapping up our development and no plans to upgrade to marko 5 as of now. But if needed i will do that.

About the declarative binding am I missing something obvious from the faqs. All i have is bunch of pub sub events. These are not dom events. How do I do the following with declarative bindings?


    init: function(config) {
        var _this = this;
        _this.config = config;
        _this.rootEl = this.el;
        _this.bindEventListeners();
    },

    bindEventListeners: function() {
        var _this = this;
        _this.subscribeTo(pubsub).on('vi-rerender__bidlayer-subpage', function() {
            _this.openOly();
        });
        if (_this.config.blolp === 1) {
            $(document).ready(function() {
                _this.openOly();
            });
        }
        _this.subscribeTo(pubsub).on('app-bid-layer__closeLayer', function() {
            _this.closeOly();
        });
        _this.subscribeTo(pubsub).on('app-bid-layer__showThrobber', function() {
            _this.showThrobber();
        });
        _this.subscribeTo(pubsub).on('app-bid-layer__hideThrobber', function() {
            _this.hideThrobber();
        });
    },

My template is


<div class="component-app-bid-layer-wrapper vi-bid-layer" w-bind='./widget' w-config='{"itemId":out.global.itemId,
                "isMobile":out.global.isMobile,
                "olyId":olyId,
                "blTrbrId":"_BL_TRBR_ID",
                "blCntId":"_BL_CNT_ID",
                "blolp":out.global.blolp}'>
patrick-steele-idem commented 9 years ago

I don't think the following will solve your problem, but the following code is equivalent and simpler:

bindEventListeners: function() {
    var _this = this;

    _this.subscribeTo(pubsub)
        .on('vi-rerender__bidlayer-subpage', function() {
            _this.openOly();
        })
        .on('app-bid-layer__closeLayer', function() {
            _this.closeOly();
        })
        .on('app-bid-layer__showThrobber', function() {
            _this.showThrobber();
        })
        .on('app-bid-layer__hideThrobber', function() {
            _this.hideThrobber();
        });

    if (_this.config.blolp === 1) {
        _this.openOly();
    }
}

I'll reach out to you separately to help debug your event emitter leak.

patrick-steele-idem commented 9 years ago

Fixed in marko-widgets@4.3.3 and marko-widgets@5.0.0-beta.11