const handler = new EventHandler(document.body, 'click')
setTimeout(() => handler.disconnect(), 5000)
for await (const event of handler.getIterator()) {
console.log(event)
}
console.log('end')
Last active
September 28, 2021 11:41
-
-
Save Lcfvs/bc70fbfc309167b1cfecb9ad924dd7b3 to your computer and use it in GitHub Desktop.
An iterable event handler
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const registry = new FinalizationRegistry(handler => handler.disconnect()) | |
class EventHandler { | |
#consumed = false | |
#options = null | |
#prevent = false | |
#promises = [] | |
#resolve = null | |
#ref = null | |
#type = null | |
#enqueue = event => { | |
if (this.#resolve) { | |
this.#resolve(event) | |
this.#next() | |
} | |
} | |
#next = () => this.#promises.push(new Promise(this.#wait)) | |
#wait = resolve => this.#resolve = resolve | |
constructor (target, type, { prevent = false, ...options } = {}) { | |
this.#ref = new WeakRef(target) | |
this.#type = type | |
this.#options = options | |
this.#prevent = prevent | |
this.#next() | |
target.addEventListener(type, this, options) | |
registry.register(target, this) | |
} | |
disconnect () { | |
this.#ref.deref()?.removeEventListener(this.#type, this, this.#options) | |
this.#resolve() | |
this.resolve = null | |
} | |
async* getIterator () { | |
if (this.#consumed) { | |
throw new Error('Unable to create an additional iterator') | |
} | |
this.#consumed = true | |
while (this.#resolve || this.#promises.length) { | |
const value = await this.#promises.shift() | |
if (value === undefined) { | |
break | |
} | |
yield value | |
} | |
} | |
async handleEvent (event) { | |
if (this.#prevent) { | |
event.preventDefault() | |
} | |
this.#enqueue(event) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@WebReflection I see your point but, imho, there is also some cases which doesn't have an event expiration, like:
The idea isn't to replace anything, just to have an easy way to do that, solving the same caveats than I presented on the MO proposal.