Skip to content

Instantly share code, notes, and snippets.

@Lcfvs
Last active September 28, 2021 13:22
Show Gist options
  • Save Lcfvs/125738d32d01892f62bbef2f575e6fa7 to your computer and use it in GitHub Desktop.
Save Lcfvs/125738d32d01892f62bbef2f575e6fa7 to your computer and use it in GitHub Desktop.
A MutationObserver providing an iterator

MutationObserver

Usage

const fragment = document.createDocumentFragment()

const append = () => fragment.append(document.createElement('div'))

const observer = new MutationObserver()

observer.observe(frag, {
  childList: true
})

append()
append()
setTimeout(append, 1000)
setTimeout(() => observer.disconnect(), 3000)
setTimeout(append, 4000)

for await (const record of observer) {
  console.log(record)
}

console.log('end')
export class MutationObserver extends globalThis.MutationObserver {
#consumed = false
#promises = []
#resolve = null
#enqueue = record => {
if (this.#resolve) {
this.#resolve(record)
this.#next()
}
}
#next = () => this.#promises.push(new Promise(this.#wait))
#wait = resolve => this.#resolve = resolve
constructor () {
super(records => {
for (const record of records) {
this.#enqueue(record)
}
})
this.#next()
}
disconnect () {
this.#resolve()
this.#resolve = null
super.disconnect()
}
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
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment