⏳
なるべくスマートに要素の出現を待つ【javascript】
はじめに
Chromeの拡張機能など書いているときに、querySelector
等で要素を取得したいときがあります。
静的なHTMLページでは、素直にquerySelector
すればいいわけですが、動的なページでやるとnull
が帰ってくる場合があります。実行時点ではその要素がDOMに存在しないからです。
document.querySelector(".dynamicElement"); //null
普通に書く
出現するまで定期的に要素があるかチェックする必要があるわけですが、setTimeout()
で普通に書くとこうなります(めんどくさかったのでChatGPTに書かせた)
function waitForElementToDisplay(selector, time, callback) {
if(document.querySelector(selector)!=null) {
callback();
return;
}
else {
setTimeout(function() {
waitForElementToDisplay(selector, time, callback);
}, time);
}
}
自分のリポジトリからも、
こんな感じで書けるわけですがスマートじゃない!コールバック嫌い!awaitが使えたらなぁ
awaitが使えれば、関数に待つ処理をまとめた上で、コールバックも使わず1行で書けるかも
let element=await waitQuerySelector(".dynamicElement");
element.click();
async function waitQuerySelector(){...}
実装
async function waitQuerySelector(selector, node=document){
let obj=null;
while(!obj){
obj=await new Promise(resolve=>setTimeout(()=>resolve(node.querySelector(selector), 100)));
}
return obj;
}
セレクタに要素が引っかかるまでawaitするquerySelectorです。
間隔はとりあえず100にしてあります。
第一引数にセレクタを指定します。
第二引数には、Elementが指定されればElement.querySelector
を呼び出します。未指定の場合はdocument.querySelector
が呼び出されます。
whileループの中では
null
null
null
null
<div class="dynamicElement">...</div>
みたいになってます。
上限を決めるときも
上のコードは、絶対に要素が出現することを前提として書いたので、上限を設定していませんが、while
のところをfor
に変えるだけで上限を設定できます。
+for(let i=0;i<10&&!obj;i++){
-while(!obj){
思いつきで書いたので間違ってたら訂正ください
Discussion