[英]Recursively and asynchronously check if html element exists
我正在与一个网页进行交互,即使在文档准备好之后,子框架中的一些更深层次的嵌套元素也会加载 - 即它们依赖于在加载文档时尚未完成的未决 ajax/api 请求。
我的意图是等到这些元素存在后再对它们做任何事情。 我可以使用 setTimeout 执行此操作并在执行任何操作之前等待任意时间,例如
setTimeout(function() {
$("#better_content .binder__toc").append(
"<h4>Experiments</h4><ul><li>This</li><li>is</li><li>a</li><li>test</li></ul>"
);
}, 5000);
但是,最好以递归和异步(非阻塞)方式继续检查所述元素(“#better_content .binder__toc”),直到未定义或 null 未返回,即元素存在。 我尝试使用 Promises 来做到这一点。 一个带计数器的简单例子如下:
static waitForElement = counter => {
counter++
return new Promise((res, rej) => {
if (counter < 5) {
this.waitForElement(counter)
.then(function() {
res("complete");
})
.catch(rej);
}
res("complete");
});
};
this.waitForElement(counter)
.then(a => console.log(a))
.catch(a => console.log(a));
以上解决成功,似乎是非阻塞。 但是,如果我替换元素选择器的计数器如下:
static waitForElement = selector => {
let found = $(document).find(selector)[0];
console.log(found);
return new Promise((res, rej) => {
if (found === undefined) {
this.waitForElement(selector)
.then(function() {
res("found");
})
.catch(rej);
}
res("found");
});
};
this.waitForElement("#better_content .binder__toc")
.then(a => {
console.log(a);
$("#better_content .binder__toc").append(
"<h4>Experiments</h4><ul><li>This</li><li>is</li><li>a</li><li>test</li></ul>"
);
})
.catch(a => console.log(a));
然后这似乎永远不会成功解决并且确实减慢了网页的速度 - 我认为因为它仍然阻塞了主线程。
任何关于我如何纠正或理解这里发生的事情的建议都非常受欢迎。
您可以使用Mutation Observer API
检查元素或元素子元素的更改。 API 会触发一个回调,您可以在其中断言您的逻辑在元素发生特定更改时采取行动。 在您的情况下,您将希望侦听将元素附加到fetch
请求的容器。
可以侦听某些更改,例如属性更改,或者在您的情况下子项的更改。 在配置中添加childList: true
这将表明您想要在添加或删除子项时执行某些操作。
这样您就不必检查元素是否存在。
查看下面的示例以查看您的示例。
const target = document.getElementById('container'); const config = { childList: true }; const observer = new MutationObserver((mutations, observer) => { /** * Loop through all changes */ mutations.forEach(mutation => { /** * Only act if it is a change in the children. */ if (mutation.type !== 'childList') { return; } /** * Loop through the added elements and check if * it is the correct element. Then add HTML to * the newly added element. */ mutation.addedNodes.forEach(node => { if (node.id === 'content') { const html = ` <h4>Experiments</h4> <ul> <li>This</li> <li>is</li> <li>a</li ><li>test</li> </ul>`; node.innerHTML = html; } }); // Stop observing. observer.disconnect(); }); }); // Observe the children in container. observer.observe(target, config); // Add content element after 2 seconds. setTimeout(function() { const content = document.createElement('div'); content.id = 'content'; target.append(content); }, 2000);
<div id="container"></div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.