From 1d8ae3eb4d1d570f1274d8bd139c39a8d44ef9a7 Mon Sep 17 00:00:00 2001 From: John Dagger Date: Tue, 19 Apr 2022 16:35:22 +0300 Subject: [PATCH 1/4] fix: handled case where event handler removed inside handler --- mqemitter.js | 2 +- test/test.js | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/mqemitter.js b/mqemitter.js index 0ba60e1..d55ff3e 100644 --- a/mqemitter.js +++ b/mqemitter.js @@ -118,7 +118,7 @@ MQEmitter.prototype._do = function (message, callback) { const matches = this._matcher.match(message.topic) this.current++ - this._parallel(this, matches, message, callback) + this._parallel(this, Array.from(matches), message, callback) return this } diff --git a/test/test.js b/test/test.js index 9fa4b45..7cc2ccb 100644 --- a/test/test.js +++ b/test/test.js @@ -128,3 +128,29 @@ test('set defaults to opts', function (t) { t.end() }) + +test('removeListener inside messageHandler', function (t) { + t.plan(3) + + const e = mq() + + function messageHandler1 (message, cb) { + t.ok(true, 'messageHandler1 called') + // removes itself + e.removeListener('hello', messageHandler1) + cb() + } + + e.on('hello', messageHandler1) + + function messageHandler2 (message, cb) { + t.ok(true, 'messageHandler2 called') + cb() + } + + e.on('hello', messageHandler2) + + e.emit({ topic: 'hello' }, function () { + t.ok(true, 'emit callback received') + }) +}) From 71361c1ce1721a0e823ded5ad58d1524048a80b6 Mon Sep 17 00:00:00 2001 From: john-dagger <104010073+john-dagger@users.noreply.github.com> Date: Tue, 17 May 2022 17:03:52 +0300 Subject: [PATCH 2/4] using for cycle instead of Array.from() --- mqemitter.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mqemitter.js b/mqemitter.js index d55ff3e..b905f63 100644 --- a/mqemitter.js +++ b/mqemitter.js @@ -116,9 +116,14 @@ MQEmitter.prototype.close = function close (cb) { MQEmitter.prototype._do = function (message, callback) { this._doing = true const matches = this._matcher.match(message.topic) + const matchesCopy = new Array(matches.length) + for (let i = 0, len = matches.length; i < len; i++) { + matchesCopy[i] = matches[i] + } this.current++ - this._parallel(this, Array.from(matches), message, callback) + + this._parallel(this, matchesCopy, message, callback) return this } From 7bef44fcc3c9f61b062e263953c729f1baaf72a9 Mon Sep 17 00:00:00 2001 From: john-dagger <104010073+john-dagger@users.noreply.github.com> Date: Wed, 18 May 2022 14:29:44 +0300 Subject: [PATCH 3/4] removing listener inside setImmediate --- mqemitter.js | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/mqemitter.js b/mqemitter.js index b905f63..0c1251e 100644 --- a/mqemitter.js +++ b/mqemitter.js @@ -74,12 +74,13 @@ MQEmitter.prototype.on = function on (topic, notify, done) { MQEmitter.prototype.removeListener = function removeListener (topic, notify, done) { assert(topic) assert(notify) - this._matcher.remove(topic, notify) - - if (done) { - setImmediate(done) - } - + const that = this + setImmediate(function () { + that._matcher.remove(topic, notify) + if (done) { + setImmediate(done) + } + }) return this } @@ -116,14 +117,9 @@ MQEmitter.prototype.close = function close (cb) { MQEmitter.prototype._do = function (message, callback) { this._doing = true const matches = this._matcher.match(message.topic) - const matchesCopy = new Array(matches.length) - for (let i = 0, len = matches.length; i < len; i++) { - matchesCopy[i] = matches[i] - } this.current++ - - this._parallel(this, matchesCopy, message, callback) + this._parallel(this, matches, message, callback) return this } From eec92cb50a1ac96036b8d5b0fee3fb3887e856fb Mon Sep 17 00:00:00 2001 From: john-dagger <104010073+john-dagger@users.noreply.github.com> Date: Thu, 19 May 2022 10:37:38 +0300 Subject: [PATCH 4/4] removed extra setImmediate() from removeListener() --- mqemitter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mqemitter.js b/mqemitter.js index 0c1251e..4a0d54a 100644 --- a/mqemitter.js +++ b/mqemitter.js @@ -78,7 +78,7 @@ MQEmitter.prototype.removeListener = function removeListener (topic, notify, don setImmediate(function () { that._matcher.remove(topic, notify) if (done) { - setImmediate(done) + done() } }) return this