"Garbage collected languages can't have memory leaks," is well established as a myth, but we still have plenty of code which refuses to clean up after itself properly.
An anonymous submitter was working with a single-page-app front-end which wraps a stream abstraction around a websocket. Messages arrive on the stream, and callbacks get invoked. When certain parameters change, new callbacks need to be registered to handle the new behavior. The old callbacks need to be unbound- and it's that step this code doesn't do.
const channelName = this.channel.name;
this.channel.bind('updated', (data) => {
if (this.channel.name === channelName) {
this.updateData(data)
}
});
The bind
method attaches a new callback to a given channel. Without a matching unbind
to remove the old callback, the old callback will sit in memory, and keep getting invoked even as it does nothing useful. Over time, this leads to performance issues.
Or, at least, it could lead to performance issues. The original developer had a… special solution to handling garbage collection. I'll let our submitter explain:
On the plus side, their cleanup logic for the component that uses this data unsubscribes all open websocket channels across the entire app on unmount, including channels owned by unrelated components, so we can rest assured that eventually they'll definitely be gone. Along with everything else.