From 9f6df89d658534f367884905c45066be979501b7 Mon Sep 17 00:00:00 2001 From: mrmaxm Date: Mon, 25 Nov 2024 10:58:03 +0200 Subject: [PATCH] implement more optimized EventHandle.off --- src/core/event-handle.js | 4 ++-- src/core/event-handler.js | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/core/event-handle.js b/src/core/event-handle.js index a2a07cb6bdc..75d02181094 100644 --- a/src/core/event-handle.js +++ b/src/core/event-handle.js @@ -32,7 +32,7 @@ class EventHandle { /** * @type {string} - * @private + * @ignore */ name; @@ -81,7 +81,7 @@ class EventHandle { */ off() { if (this._removed) return; - this.handler.off(this.name, this.callback, this.scope); + this.handler.offByHandle(this); } on(name, callback, scope = this) { diff --git a/src/core/event-handler.js b/src/core/event-handler.js index 1f30e959a4d..1d58fc8bd81 100644 --- a/src/core/event-handler.js +++ b/src/core/event-handler.js @@ -222,6 +222,40 @@ class EventHandler { return this; } + /** + * Detach an event handler from an event using EventHandle instance. More optimal remove + * as it does not have to scan callbacks array. + * + * @param {EventHandle} handle - Handle of event. + * @ignore + */ + offByHandle(handle) { + const name = handle.name; + handle.removed = true; + + // if we are removing a callback from the list that is executing right now + // ensure we preserve initial list before modifications + if (this._callbackActive.has(name) && this._callbackActive.get(name) === this._callbacks.get(name)) { + this._callbackActive.set(name, this._callbackActive.get(name).slice()); + } + + const callbacks = this._callbacks.get(name); + if (!callbacks) { + return this; + } + + const ind = callbacks.indexOf(handle); + if (ind !== -1) { + callbacks.splice(ind, 1); + + if (callbacks.length === 0) { + this._callbacks.delete(name); + } + } + + return this; + } + /** * Fire an event, all additional arguments are passed on to the event listener. *