EventEmitter memory leak?
drewvolz opened this issue · 4 comments
I mounted and unmounted the component that scans for devices a few dozen times and received this message.
(node) warning: possible EventEmitter memory leak detected. 11 listeners added.
Use emitter.setMaxListeners() to increase limit.
reactConsoleErrorHandler @ ExceptionsManager.js:71
console.error @ YellowBox.js:62
EventEmitter.addListener @ events.js:138
componentDidMount @ network-scan.js:41
proxiedComponentDidMount @ createPrototypeProxy.js:61
(anonymous) @ ReactCompositeComponent.js:353
measureLifeCyclePerf @ ReactCompositeComponent.js:85
(anonymous) @ ReactCompositeComponent.js:352
notifyAll @ CallbackQueue.js:73
close @ ReactNativeReconcileTransaction.js:36
closeAll @ Transaction.js:222
perform @ Transaction.js:163
perform @ Transaction.js:149
perform @ ReactUpdates.js:95
flushBatchedUpdates @ ReactUpdates.js:199
closeAll @ Transaction.js:222
perform @ Transaction.js:163
batchedUpdates @ ReactDefaultBatchingStrategy.js:65
batchedUpdates @ ReactUpdates.js:111
_receiveRootNodeIDEvent @ ReactNativeEventEmitter.js:126
receiveTouches @ ReactNativeEventEmitter.js:212
__callFunction @ MessageQueue.js:242
(anonymous) @ MessageQueue.js:108
guard @ MessageQueue.js:46
callFunctionReturnFlushedQueue @ MessageQueue.js:107
(anonymous) @ debuggerWorker.js:71
This might have happened because I am not making use of removeDeviceListeners
. I did not see it as part of the documentation. Maybe the docs should receive an update.
Hi, thanks for the report!
Yes indeed, I forgot to update the readme, will do. Could you confirm it fixes your issues though?
I believe, this problem is not completely fixed. Here is why:
Since every new instance of the Zeroconf
object starts with an empty this._dListeners
in the constructor, if somehow that specific instance is lost during the application flow, there is no way to remove the previous listeners from a new instance of Zeroconf
.
I escape this problem by manually call DeviceEventEmitter.removeAllListeners()
before creating Zeroconf
, like this:
import { DeviceEventEmitter } from "react-native";
import Zeroconf from "react-native-zeroconf";
/* important part */
DeviceEventEmitter.removeAllListeners("RNZeroconfStart");
DeviceEventEmitter.removeAllListeners("RNZeroconfStop");
DeviceEventEmitter.removeAllListeners("RNZeroconfError");
DeviceEventEmitter.removeAllListeners("RNZeroconfFound");
DeviceEventEmitter.removeAllListeners("RNZeroconfRemove");
DeviceEventEmitter.removeAllListeners("RNZeroconfResolved");
DeviceEventEmitter.removeAllListeners("RNZeroconfServiceRegistered");
DeviceEventEmitter.removeAllListeners("RNZeroconfServiceUnregistered");
/* */
const zeroconf = new Zeroconf();
My suggestion is to do this in the removeDeviceListeners
function (and maybe in the constructor) instead of calling remove
on currently saved listeners in this._dListeners
... not sure if it's the cleanest solution though.