为什么我在 Driver.FindElementsByCssSelector(); 刚刚检索到的元素上得到 StaleElementReferenceException;
Why I'm getting StaleElementReferenceException on just retrieved elements by Driver.FindElementsByCssSelector();
我使用edge webdriver在页面(SPA)上查找元素,并立即模拟点击。
但是,我收到 OpenQA.Selenium.StaleElementReferenceException:过时的元素参考:元素未附加到页面文档。
如果元素在查找元素和单击之间被 SPA 框架重新呈现,我添加了一些重试逻辑,但我仍然收到错误。
IWebElement FirstCell => Driver.FindElementsByCssSelector(".simple-grid .sg-row>.sg-cell").FirstOrDefault();
void Test()
{
try
{
FirstCell.Click();
}
catch (StaleElementReferenceException)
{
FirstCell.Click(); //retry - this should find element againand return new instance
}
}
注意,在重试块中我得到了新的元素引用
如 here 和许多其他教程和问题所述 StaleElementReferenceException
通过 Driver.FindElementsByCssSelector(".simple-grid .sg-row>.sg-cell")
命令,您实际上捕获了与传递的定位器匹配的 Web 元素并将对它的引用存储在IWebElement FirstCell
.
但是由于网页仍在动态变化,尚未最终构建,因此您存储的引用很快就会变得陈旧、陈旧、无效,因为 web 元素已更改。
这就是为什么通过在 try
块中包含 FirstCell.Click()
你会得到 StaleElementReferenceException
.
尝试在 catch
块中涉及完全相同的操作将再次抛出 StaleElementReferenceException
,因为您仍在使用已知的无效(陈旧)FirstCell
引用。
要使代码正常工作,您可以做的是在 catch 块中获取该元素引用 Again 并尝试单击它。
像这样:
IWebElement FirstCell => Driver.FindElementsByCssSelector(".simple-grid .sg-row>.sg-cell").FirstOrDefault();
void Test()
{
try
{
FirstCell.Click();
}
catch (StaleElementReferenceException)
{
FirstCell = Driver.FindElementsByCssSelector(".simple-grid .sg-row>.sg-cell").FirstOrDefault();
FirstCell.Click(); //retry - Now this indeed should find element again and return new instance
}
}
然而,这也不一定有效,因为页面可能仍未完全稳定。
要完成这项工作,您可以循环执行此操作,如下所示:
void Test()
{
IWebElement FirstCell;
for(int i=0;i<10;i++){
try
{
FirstCell = Driver.FindElementsByCssSelector(".simple-grid .sg-row>.sg-cell").FirstOrDefault();
FirstCell.Click();
}
catch (StaleElementReferenceException)
{
System.Threading.Thread.Sleep(200);
}
}
}
我使用edge webdriver在页面(SPA)上查找元素,并立即模拟点击。
但是,我收到 OpenQA.Selenium.StaleElementReferenceException:过时的元素参考:元素未附加到页面文档。
如果元素在查找元素和单击之间被 SPA 框架重新呈现,我添加了一些重试逻辑,但我仍然收到错误。
IWebElement FirstCell => Driver.FindElementsByCssSelector(".simple-grid .sg-row>.sg-cell").FirstOrDefault();
void Test()
{
try
{
FirstCell.Click();
}
catch (StaleElementReferenceException)
{
FirstCell.Click(); //retry - this should find element againand return new instance
}
}
注意,在重试块中我得到了新的元素引用
如 here 和许多其他教程和问题所述 StaleElementReferenceException
通过 Driver.FindElementsByCssSelector(".simple-grid .sg-row>.sg-cell")
命令,您实际上捕获了与传递的定位器匹配的 Web 元素并将对它的引用存储在IWebElement FirstCell
.
但是由于网页仍在动态变化,尚未最终构建,因此您存储的引用很快就会变得陈旧、陈旧、无效,因为 web 元素已更改。
这就是为什么通过在 try
块中包含 FirstCell.Click()
你会得到 StaleElementReferenceException
.
尝试在 catch
块中涉及完全相同的操作将再次抛出 StaleElementReferenceException
,因为您仍在使用已知的无效(陈旧)FirstCell
引用。
要使代码正常工作,您可以做的是在 catch 块中获取该元素引用 Again 并尝试单击它。
像这样:
IWebElement FirstCell => Driver.FindElementsByCssSelector(".simple-grid .sg-row>.sg-cell").FirstOrDefault();
void Test()
{
try
{
FirstCell.Click();
}
catch (StaleElementReferenceException)
{
FirstCell = Driver.FindElementsByCssSelector(".simple-grid .sg-row>.sg-cell").FirstOrDefault();
FirstCell.Click(); //retry - Now this indeed should find element again and return new instance
}
}
然而,这也不一定有效,因为页面可能仍未完全稳定。
要完成这项工作,您可以循环执行此操作,如下所示:
void Test()
{
IWebElement FirstCell;
for(int i=0;i<10;i++){
try
{
FirstCell = Driver.FindElementsByCssSelector(".simple-grid .sg-row>.sg-cell").FirstOrDefault();
FirstCell.Click();
}
catch (StaleElementReferenceException)
{
System.Threading.Thread.Sleep(200);
}
}
}