diff --git a/src/socket.ts b/src/socket.ts index fcb4c84..c1bf743 100644 --- a/src/socket.ts +++ b/src/socket.ts @@ -453,9 +453,18 @@ export class FluentSocket extends EventEmitter { this.processMessages(protocol.decodeServerStream(this.passThroughStream)); return new Promise((resolve, reject) => { - // This may call both resolve and reject, but the ES standard says this is OK - this.once(FluentSocketEvent.CONNECTED, () => resolve()); - this.once(FluentSocketEvent.ERROR, err => reject(err)); + const onConnected = () => { + resolve(); + // Avoid a memory leak and remove the other listener + this.removeListener(FluentSocketEvent.ERROR, onError); + }; + const onError = (err: Error) => { + reject(err); + // Avoid a memory leak and remove the other listener + this.removeListener(FluentSocketEvent.CONNECTED, onConnected); + }; + this.once(FluentSocketEvent.CONNECTED, onConnected); + this.once(FluentSocketEvent.ERROR, onError); }); } @@ -483,7 +492,7 @@ export class FluentSocket extends EventEmitter { this.onMessage(message); } } catch (e) { - this.close(CloseState.RECONNECT, e); + this.close(CloseState.RECONNECT, e as Error); } } diff --git a/test/test.socket.ts b/test/test.socket.ts index 00733d0..b098ea5 100644 --- a/test/test.socket.ts +++ b/test/test.socket.ts @@ -60,6 +60,19 @@ describe("FluentSocket", () => { sinon.assert.calledOnce(connectStub); }); + it("should not preserve error handlers after connect", done => { + const {socket, connectStub} = createFluentSocket({disableReconnect: true}); + + socket.on(FluentSocketEvent.WRITABLE, () => { + expect(socket.listenerCount(FluentSocketEvent.ERROR)).to.equal(0); + done(); + }); + + socket.connect(); + + sinon.assert.calledOnce(connectStub); + }); + it("should not block for draining on write by default", done => { const {socket, stream, connectStub} = createFluentSocket({ disableReconnect: true,