typescript - Jsdom hur man "kontrollerar närvaron av ett specifikt element."?
I jsdom-dokumentationen https://github.com/jsdom/jsdom, under Asynchronous script loading, rekommenderas det att pollning efter närvaron av ett specifikt element som en metod för att säkerställa att DOM laddar det du behöver.
Koden nedan är min tolkning av att göra det:
const elementOnPage = (arg: HTMLElement | null): HTMLElement => {
let tried = arg;
while (tried === null) {
// debugger;
console.log("nothing yet");
tried = arg;
}
return tried;
};
anropa sedan funktionen på detta sätt:
...
await elementOnPage(
dom.window.document.querySelector("#some element that I know will eventually be loaded onto the page")
);
...
Trots att jag vet att detta element så småningom kommer att laddas, orsakar detta en oändlig loop. Det verkar som om argumentet kan utvärderas till null första gången, sedan sättas till null varje efterföljande gång, men jag är inte säker. I vilket fall som helst försökte jag också använda
dom.window.document.getElementsByClassName("some class that will eventually have member elements")
och kontrollerar att den resulterande samlingens längd inte är 0, men detta ger samma oändliga loop. Jag tror inte att DOM-selektormetoden är problemet. Så, vad orsakar denna oändliga loop, och/eller finns det ett bättre sätt att pollera efter ett element?
Svar #1
Några missförstånd här:
Anropet till
elementOnPage(querySelector(...))körs en gång (om inte koden själv ligger i någon loop eller händelsehanterare). Om DOM-elementet finns vid tidpunkten för körning returnerar det omedelbart, annars kommer selektorn aldrig att köras igen så din funktion kommer att köras oändligt mednullsom argument det fick.I JavaScript är loopar som
whileblockande (inkluderar inte workers som är orelaterade här), så du låser i princip tråden. Även om du skulle köraquerySelectorfrån insidan av loopen igen skulle det resultera i en oändlig loop.
För att utföra polling utan att blockera JS-exekvering vill du använda setInterval eller setTimeout.
Dessutom bör en awaitbar funktion returnera en Promise (tekniskt sett kan du awaita vad som helst, men ett promise är ditt sätt att göra det användbart).
Här är ett outprovat exempel:
const elementOnPage = (query: string, timeout: number = 10000): Promise<HTMLElement | null> => {
return new Promise((resolve, reject) => {
const startTime = Date.now();
const tryQuery = () => {
const elem = dom.window.document.querySelector(query);
if (elem) resolve(elem); // Found the element
else if (Date.now() - startTime > timeout) resolve(null); // Give up eventually
else setTimeout(tryQuery, 10); // check again every 10ms
}
tryQuery(); // Initial check
});
};
// Elsewhere:
const elem = await elementOnPage("#some_element");
