jsdom如何"poll for the presence of a specific element."?
Jsdom how to "poll for the presence of a specific element."?
在 jsdom 文档 https://github.com/jsdom/jsdom 中,在异步脚本加载下,建议轮询是否存在特定元素作为确保 dom 加载您的内容的方法需要。
下面的代码是我对此的解释:
const elementOnPage = (arg: HTMLElement | null): HTMLElement => {
let tried = arg;
while (tried === null) {
// debugger;
console.log("nothing yet");
tried = arg;
}
return tried;
};
然后像这样调用函数:
...
await elementOnPage(
dom.window.document.querySelector("#some element that I know will eventually be loaded onto the page")
);
...
尽管我知道这个元素最终会被加载,但这会导致无限循环。似乎参数可能第一次被评估为 null,然后每次都设置为 null,但我不确定。无论如何,我也尝试使用
dom.window.document.getElementsByClassName("some class that will eventually have member elements")
并检查生成的集合长度是否不为 0,但此 returns 是同一个无限循环。我不认为 dom 选择器方法是问题所在。那么,是什么导致了这个无限循环,and/or 是否有更好的方法来轮询元素?
这里有几个误解:
对elementOnPage(querySelector(...))
的调用被执行一次(除非该代码本身在某个循环或事件处理程序中)。如果 DOM 元素在执行时存在,它会立即 returns ,否则它将永远不会再次执行选择器,所以你的函数将 运行 无休止地以 null
作为参数给了。
在JavaScript中,像while
这样的循环是阻塞的(不包括这里不相关的worker),所以你基本上锁定了线程。即使您从循环内部重新 运行ning querySelector
也会导致无限循环。
要在不阻塞 JS 执行的情况下执行轮询,您要使用 setInterval
or setTimeout
。
此外,可等待函数应该 return Promise
(从技术上讲,您可以 await
任何东西,但承诺是使它有用的手段)。
这是一个未经测试的例子:
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");
在 jsdom 文档 https://github.com/jsdom/jsdom 中,在异步脚本加载下,建议轮询是否存在特定元素作为确保 dom 加载您的内容的方法需要。
下面的代码是我对此的解释:
const elementOnPage = (arg: HTMLElement | null): HTMLElement => {
let tried = arg;
while (tried === null) {
// debugger;
console.log("nothing yet");
tried = arg;
}
return tried;
};
然后像这样调用函数:
...
await elementOnPage(
dom.window.document.querySelector("#some element that I know will eventually be loaded onto the page")
);
...
尽管我知道这个元素最终会被加载,但这会导致无限循环。似乎参数可能第一次被评估为 null,然后每次都设置为 null,但我不确定。无论如何,我也尝试使用
dom.window.document.getElementsByClassName("some class that will eventually have member elements")
并检查生成的集合长度是否不为 0,但此 returns 是同一个无限循环。我不认为 dom 选择器方法是问题所在。那么,是什么导致了这个无限循环,and/or 是否有更好的方法来轮询元素?
这里有几个误解:
对
elementOnPage(querySelector(...))
的调用被执行一次(除非该代码本身在某个循环或事件处理程序中)。如果 DOM 元素在执行时存在,它会立即 returns ,否则它将永远不会再次执行选择器,所以你的函数将 运行 无休止地以null
作为参数给了。在JavaScript中,像
while
这样的循环是阻塞的(不包括这里不相关的worker),所以你基本上锁定了线程。即使您从循环内部重新 运行ningquerySelector
也会导致无限循环。
要在不阻塞 JS 执行的情况下执行轮询,您要使用 setInterval
or setTimeout
。
此外,可等待函数应该 return Promise
(从技术上讲,您可以 await
任何东西,但承诺是使它有用的手段)。
这是一个未经测试的例子:
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");