DEV Community

Cover image for Memory leak by anonymous functions

Memory leak by anonymous functions

Jeevan Kishore on May 30, 2020

With introduction of fat arrow functions ➕ the implicit bind magic, JS developers found an everlasting 💛 towards them. Although they were eye plea...
Collapse
 
miketalbot profile image
Mike Talbot ⭐

I like to write anonymous event handlers on occasion and my work app is all Inversion of Control - so we have a master event bus etc. We just use hooks to add the events and then it's fine as it is properly removed.

We mostly use our master event bus which has a special hook, but the generic one looks like this:

export function useEvent(emitter, pattern, handler) {
    if (!handler) {
        ;[emitter, pattern, handler] = [events, emitter, pattern]
    }
    let runner = (...params) => {
        handler(...params)
    }
    useEffect(() => {
        if (emitter) {
            if (emitter.addEventListener) {
                emitter.addEventListener(eventName(pattern), runner)
            } else {
                emitter.addListener(eventName(pattern), runner)
            }
        }
        return () => {
            if (emitter.removeEventListener) {
                emitter.removeEventListener(eventName(pattern), runner)
            } else {
                emitter.removeListener(eventName(pattern), runner)
            }
        }
    })
}

Used like this:

function SomeComponent() {
     useEvent(window, 'resize', ()=>console.log(innerWidth, innerHeight))
}
Collapse
 
jwp profile image
JWP

Why aren't anonymous event handlers destroyed when the view is destroyed? Sounds like a design point issue.

Collapse
 
miketalbot profile image
Mike Talbot ⭐ • Edited

It would be fair to say if the event emitter is destroyed then they are unreachable and are released. If you attach to a global event handler or something that will survive a while, they aren't removed because nothing calls removeListener. It would be true of a non-anonymous listener true I guess.

I'm guessing people aren't working out how to remember the anonymous function to then call removeListener. It's one of those, the sugar is so sweet someone didn't notice the sudden weight gain ;)

Collapse
 
jeevankishore profile image
Jeevan Kishore • Edited

The responsibility is likely delegated to the user to remove listeners when they feel it's time to do so.

I agree with @miketalbot on how people overlook it.

Collapse
 
savagepixie profile image
SavagePixie

How is this issue different for anonymous functions declared using the function keyword?

Collapse
 
jeevankishore profile image
Jeevan Kishore • Edited

@savagepixie It isn't different, as long as there are creation of objects which cannot be GC'd the issue remains the same. The article addresses the latter as people prefer to use the fat arrows widely because of binding