Brandon Brandon - 1 month ago 7
Javascript Question

How do I deactivate a MutationsObserver after n seconds?

I'm writing a

generator
function (wrapped w/ a wrapper from the
co
library, allowing me to
yield
to
Promises
, a la
async await
).

The script calls
button.click()
on a DOM Node, then waits for a popup to appear using the MutationObserver API, which I've wrapped in a
promise
:

const startDOMObservable = (domNode) => {

return new Promise((resolve) => {

let observer = new MutationObserver(function (mutations, obs) {
mutations.forEach(function (mutation) {
obs.disconnect()
resolve(mutations, obs)
})
})
observer.observe(targetNode, { childList: true })
})
}


In the invoker, ie, the
generator
, I call this function like so:

document.querySelector('.the_button').click()
const mutations = yield startDOMObservable(
document.querySelector('.parent_of_popup')
)


(ETA: this generator/promise pattern may look a little strange, but it works (so far, i think). h/t to David Walsh blog for writing about it)

Since the generator function that calls
startDOMObservable
is
yield
ing, how do I handle instances where no mutation occurs? When that happens, I'd like to
resolve
or
reject
the promise w/ an appropriate message.

Answer

You'd add the timeout and disconnect the observer after n seconds, and then also resolve or reject

const startDOMObservable = (domNode, secs) => {

    return new Promise((resolve, reject) => {

        let observer = new MutationObserver(function(mutations, obs) {
            obs.disconnect();
            clearTimeout( timeout );
            resolve(mutations, obs);
        });

        observer.observe(domNode, {
            childList: true
        });

        let timeout = setTimeout(() => {
            observer.disconnect();
            reject('Nothing happened ?');
        }, secs * 1000);
    })
}

and then

const mutations = yield startDOMObservable(
   document.querySelector('.parent_of_popup'), 2 // <- seconds to wait
)

document.querySelector('.the_button').click()
Comments