首页 > 解决方案 > 为什么我的 MutationObserver 对象没有断开连接?

问题描述

我有一个 MutationObserver 对象,该对象在函数内使用其回调函数进行初始化,并观察一个节点,该节点的其中一个子文本每两秒更改一次,以便将另一个节点的文本更改为始终与另一个节点的文本相似回调函数。

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

但是即使 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 属性之一作为参数调用函数 changeText() 时,MutationObserver 被初始化并开始观察,但是当参数与 id 不匹配时,MutationObserver 应该停止但在我的情况下它会继续运行并且显示的消息是“观察者未定义”,即使在它被定义为 MutationObserver 并且它继续观察之后。

标签: javascript

解决方案


您必须将 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);
    }
};

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


推荐阅读