Nermin
Nermin

Reputation: 935

MutationObserver observe only once

I want to create a MutationObserver which only exists for one observation at a time. Just like the addEventListener once parameter.

So the problem I'm having is that with the snippet below, a new observer is created for each click but they are never "exited" or "closed" and therefore I get more than one console.log per click for each button press.

document.querySelector('.btn').addEventListener('click', () => {
  const targetEl = document.querySelector('.target')
  setTimeout(() => {
    targetEl.classList.add("red")
  }, 500);


  function callback(mutationList, obs) {
    mutationList.forEach(mutation => {
      if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
        console.log("I should only run once per button press")
      }
    })
  }
  
  const observer = new MutationObserver(callback)
  observer.observe(targetEl, {attributes: true})
})
.red {
  background-color: red !important;
}
<button class="btn">Press me multiple times</button>

<div class="target" style="width: 100px; height: 100px; background-color: blue"></div>

Upvotes: 0

Views: 2546

Answers (2)

Barmar
Barmar

Reputation: 780798

Call MutationObserver.disconnect() to stop watching for mutations.

document.querySelector('.btn').addEventListener('click', () => {
  const targetEl = document.querySelector('.target')
  setTimeout(() => {
    targetEl.classList.add("red")
  }, 500);


  function callback(mutationList, obs) {
    obs.disconnect();
    mutationList.forEach(mutation => {
      if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
        console.log("I should only run once per button press")
      }
    })
  }
  
  const observer = new MutationObserver(callback)
  observer.observe(targetEl, {attributes: true})
})
.red {
  background-color: red !important;
}
<button class="btn">Press me multiple times</button>

<div class="target" style="width: 100px; height: 100px; background-color: blue"></div>

Upvotes: 2

Salketer
Salketer

Reputation: 15711

In your callback, obs.disconnect();

  function callback(mutationList, obs) {
    mutationList.forEach(mutation => {
      if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
        obs.disconnect();
        console.log("I should only run once per button press")
      }
    })
  }
  
  const observer = new MutationObserver(callback)
  observer.observe(targetEl, {attributes: true})

Upvotes: 0

Related Questions