[英]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.