为什么我的MutationObserver对象没有断开连接?

时间:2019-02-26 15:55:10

标签: javascript

我有一个MutationObserver对象,该对象在函数内用其回调函数初始化,并观察到一个节点,该节点的子文本之一每两秒钟更改一次,以便将另一个节点的文本更改为始终与另一个具有回调功能。

在同一函数中,我检查对象的属性是否与函数的参数相同。如果是,则将初始化MutationObserver对象,如果未初始化,则将在try catch中断开MutationObserver对象的连接。

但是,即使MutationObserver对象似乎已成功断开连接,它仍然会执行其回调函数并即使断开连接也会更改同一节点的文本。

我尝试在函数外部声明观察者变量,但是它仍然无法正常工作。 这是我的代码通常如何工作的示例:

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;
    }
}

因此,当使用对象的id属性之一作为参数调用一次function changeText()时,MutationObserver会初始化并开始观察,但是当参数与id不匹配时,MutationObserver应该停止,但就我而言它继续前进,显示的消息是“未定义观察者”,即使它被定义为MutationObserver之后也一直观察。

1 个答案:

答案 0 :(得分:0)

您必须将try / catch移到函数顶部,以便在观察者已经存在时,在覆盖它之前将其删除。

请考虑以下情形:

我单击一个有效的ID,并附加了MutationObserver。

我单击第二个有效ID,将附加一个新的MutationObserver,并且try / catch永远不会运行以断开先前的观察者的连接,因为循环内的return语句将终止该函数,使其无法进入try / catch块。

因此,observer现在引用了您创建的第二个回调,您将无法删除第一个回调。

所以我会写类似的东西

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);
    }
};

这是一个很好的例子,为什么使用全局变量在函数内部进行修改而不使用显式参数会导致问题,因为值可能会在几个不同的位置发生变化。