1

I have a MutationObserver object that is initialized with its callback function inside a function and observes a node that has one of its children's text changed every two seconds in order to change the text of another node to always be similar to that of the other one with the callback function.

In that same function, I check if an attribute of an object is the same as the parameter of the function. If it is, the MutationObserver object is initialized and if it isn't, the MutationObserver object is disconnected inside a try catch.

But even if the MutationObserver object is seemingly disconnected successfully, it still does its callback function and changes the text of the same node even though it is disconnected.

I tried declaring the observer variable outside the function but it still doesn't work. Here is an example of how my code works in general:

var observer;
var objectList = [{
        id: 1,
        text: "ObjectA",
    },
    {
        id: 2,
        text: "ObjectB",
    },
    {
        id: 3,
        text: "ObjectC",
    }
]

function changeText(id) {
    var i, callback, config;
    for (i = 0; i < objectList.length; i++) {
        if (objectList[i].id === id) {
            config = {
                characterData: true
            };
            callback = function () {
                document.getElementById("textNode").innerHTML = document.getElementById("otherTextNode").innerHTML;
            };
            observer = new MutationObserver(callback);
            observer.observe(document.getElementById("otherTextNode"), config)
            return;
        }
    }
    document.getElementById("textNode").innerHTML = "";
    try {
        observer.disconnect();
    } catch (e) {
        document.getElementById("textNode").innerHTML = e.message;
    }
}

So when the function changeText() is called once with one of the objects' id property as the parameter, the MutationObserver is initialized and begins observing but when the parameter does not match the ids, the MutationObserver should stop but in my case it keeps going and the message displayed is "observer is undefined" even AFTER it was defined as a MutationObserver and that it keeps observing.

montrealist
  • 5,593
  • 12
  • 46
  • 68
Mr.D
  • 79
  • 6
  • Because you didn't call `observer.disconnect();` for each instance of the observer you create? – Pete Feb 26 '19 at 17:28
  • You could try disconnecting the observer in it's callback function: https://stackoverflow.com/questions/41323897/disconnect-mutation-observer-from-callback-function – Pete Feb 26 '19 at 17:33
  • Thanks it worked but a new problem for me arose when I tried it... I forgot to mention that while "otherTextNode" appears on the webpage, "textNode" only appears on a bootstrap modal and I need that "textNode" continues changing while the modal is still there but when the observer is disconnected form inside its callback function, "textNode" changes only once when I need it to continue changing. – Mr.D Feb 27 '19 at 07:36
  • Alright, my problem was resolved on the answer bellow. – Mr.D Feb 27 '19 at 07:55

1 Answers1

0

You have to move the try/catch to the top of the function, so that when an observer already exists, you remove it before overwriting it.

Consider the following scenario:

I click a valid id, a MutationObserver is attached.

I click a second valid id, a new MutationObserver is attached and the try/catch never runs to disconnect the previous observer, since the return statement inside the loop will terminate the function from getting to the try/catch block.

So now observer refers to the second callback you created and you have no way to remove the first callback anymore.

So I would write something like:

function changeText(id) {
    if ( observer ) observer.disconnect();
    const match = objectList.find( entry => entry.id === id );
    if ( match ) {
        config = {
            characterData: true
        };
        callback = function () {
            document.getElementById("textNode").innerHTML = document.getElementById("otherTextNode").innerHTML;
        };
        observer = new MutationObserver(callback);
        observer.observe(document.getElementById("otherTextNode"), config);
    }
};

This is a good example why using global variables you modify inside functions instead of using explicit parameters can lead to issues, since the value can change in several different places.

Shilly
  • 8,511
  • 1
  • 18
  • 24
  • Thanks it worked! Originally, observer was a variable inside the function but then I moved it as a global variable because I thought because I didn't disconnect it when it was first initialized on the first call of the function, it couldn't be disconnected after the following calls. – Mr.D Feb 27 '19 at 07:49