Selenium4下如何从ExpectedCondition对象返回布尔值解决JS等待报错
问题原因
Selenium 4调整了WebDriverWait#until的实现逻辑:当传入的预期条件不满足时,方法会直接抛出TimeoutException而非返回false,你原本的&&拼接写法逻辑就无法正常执行,同时分开等待两个条件会导致总最大等待时间变成60秒,不符合你预设的30秒超时要求。
修复方案
使用Selenium内置的ExpectedConditions.and()方法将两个预期条件合并,一次性传入until方法即可,既符合总超时30秒的要求,也能正确判断两个条件的结果。
修改后的完整代码
public static boolean waitForJStoLoad() { WebDriverWait wait = new WebDriverWait(getDriver(), Duration.ofSeconds(30)); // 等待jQuery加载完成 ExpectedCondition<Boolean> jQueryLoad = new ExpectedCondition<Boolean>() { @Override public Boolean apply(WebDriver arg0) { try { Long state = (Long) ((JavascriptExecutor) arg0).executeScript("return jQuery.active"); return (state == 0); } catch (Exception e) { // 页面不存在jQuery时直接返回true,兼容无jQuery的站点 return true; } } }; // 等待JavaScript加载完成 ExpectedCondition<Boolean> jsLoad = new ExpectedCondition<Boolean>() { @Override public Boolean apply(WebDriver arg0) { String state = (String) ((JavascriptExecutor) arg0).executeScript("return document.readyState;"); return state.equalsIgnoreCase("complete"); } }; // 合并两个条件,总等待时长不超过30秒 return wait.until(ExpectedConditions.and(jQueryLoad, jsLoad)); }
可选简化写法(Java 8+ 支持lambda)
如果你的项目使用Java 8及以上版本,可以直接用lambda简化两个预期条件的定义,代码更简洁:
public static boolean waitForJStoLoad() { WebDriverWait wait = new WebDriverWait(getDriver(), Duration.ofSeconds(30)); ExpectedCondition<Boolean> jQueryLoad = driver -> { try { return ((Long) ((JavascriptExecutor) driver).executeScript("return jQuery.active")) == 0; } catch (Exception e) { return true; } }; ExpectedCondition<Boolean> jsLoad = driver -> "complete".equalsIgnoreCase(((String) ((JavascriptExecutor) driver).executeScript("return document.readyState"))); return wait.until(ExpectedConditions.and(jQueryLoad, jsLoad)); }
注意事项
- 注意导入正确的依赖包:
import org.openqa.selenium.support.ui.ExpectedConditions; - 如果不需要兼容无jQuery的页面,可以把jQuery判断的catch块逻辑调整为你需要的处理逻辑。
内容的提问来源于stack exchange,提问作者fujiwara_tofu
相关产品推荐
相关产品推荐

