javascript - 为什么我的 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 并且它继续观察之后。
解决方案
您必须将 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);
}
};
这是一个很好的例子,为什么在函数内部使用全局变量而不是使用显式参数会导致问题,因为值可以在几个不同的地方发生变化。
推荐阅读
- javascript - AngularJS - 在新浏览器窗口中打开控制器时,单击子窗口随机触发父窗口上的事件
- java - Java 线程限制,JVM 9
- celery - 如何阻止芹菜中的工人?
- javascript - 发布依赖于 3rd 方 npm 包的 Typescript 包
- css - 使用 D3 选择通配符
- javascript - 按预期顺序检索 GET 请求响应时出现问题
- spotify - Spotify 网络钩子?
- csv - 门:使用 groovy 将门导出到 csv 文件
- python - 为一段不简单的代码创建一个while循环
- windows - 从 Docker 访问 TFS 代码