Selenium 和异步 JavaScript 调用
Selenium and asynchronous JavaScript calls
我对 Selenium 和 JavaScript-回调函数还很陌生,我有一个大问题我自己解决不了。我需要使用 JavaScript 的指定变量。如果我使用 GoogleChrome 打开页面并使用控制台输入我的 JavaScript-代码,我可以使用如下方式获取变量:
1. var myId;
2. getSomeIdStuffInfo("somestuff",function(docId)(myId = docId));
3. return myId;
如果我一步一步地输入这一行,我很容易得到正确的值 myId。但是,当然,如果我尽可能快地执行这三行,我会得到 null 作为 return 值,因为当我 return myId 时回调函数没有完成。 SOOOO .. 如果我像这样使用硒:
JavascriptExecutor js = (JavascriptExecutor) driver;
String docInfoVal = (String) js.executeScript("" +
"var myId; " +
"getCurrentDocumentInfo(\"somestuff\"," +
"function(docId) {" +
"myId = docId;" +
"}" +
");" +
"return myId;");
结果我只得到空值。所以...不知何故我必须 "wait" 回调函数,直到我 return myId。我必须使用 executeAsyncScript 吗?如何使用?我坐在上面几个小时,尝试了不同的东西,但我就是找不到答案。
在此先感谢您的帮助!
对于异步代码,您必须使用 executeAsyncScript
:
JavascriptExecutor js = (JavascriptExecutor) driver;
String docInfoVal = (String) js.executeAsyncScript("" +
"var done = arguments[0]; " +
"getCurrentDocumentInfo(\"somestuff\"," +
"function(docId) {" +
"done(docId);" +
"}" +
");");
您使用 executeAsyncScript
调用的脚本会将回调添加到传递给它的参数列表中。由于您没有向脚本传递任何参数,因此 arguments[0]
包含回调。您的代码必须在完成工作后调用此回调。你给回调的值就是executeAsyncScript
returns.
的值
在上面的代码中,我将对 done
的调用放在一个匿名函数中,但代码可以写得更简洁:
JavascriptExecutor js = (JavascriptExecutor) driver;
String docInfoVal = (String) js.executeAsyncScript("" +
"var done = arguments[0]; " +
"getCurrentDocumentInfo(\"somestuff\", done);");
甚至:
JavascriptExecutor js = (JavascriptExecutor) driver;
String docInfoVal = (String) js.executeAsyncScript(
"getCurrentDocumentInfo('somestuff', arguments[0]);");
尽管这与@Louis said.You 必须事先设置 setScriptTimeout
以使脚本通过的内容几乎相同。
The default timeout for a script to be executed is 0ms. In most cases,
including the examples below, one must set the script timeout
WebDriver.Timeouts.setScriptTimeout(long,
java.util.concurrent.TimeUnit) beforehand to a value sufficiently
large enough.
下面是一个例子,我等待 10 秒 return 一个字符串
driver.manage().timeouts().setScriptTimeout(20, TimeUnit.SECONDS);//important
JavascriptExecutor executor = (JavascriptExecutor) driver;
String val = (String) executor.executeAsyncScript(""
+ "var done=arguments[0]; "
+ "setTimeout(function() {"
+ " done('tada');"
+ " }, 10000);");
System.out.println(val);
我对 Selenium 和 JavaScript-回调函数还很陌生,我有一个大问题我自己解决不了。我需要使用 JavaScript 的指定变量。如果我使用 GoogleChrome 打开页面并使用控制台输入我的 JavaScript-代码,我可以使用如下方式获取变量:
1. var myId;
2. getSomeIdStuffInfo("somestuff",function(docId)(myId = docId));
3. return myId;
如果我一步一步地输入这一行,我很容易得到正确的值 myId。但是,当然,如果我尽可能快地执行这三行,我会得到 null 作为 return 值,因为当我 return myId 时回调函数没有完成。 SOOOO .. 如果我像这样使用硒:
JavascriptExecutor js = (JavascriptExecutor) driver;
String docInfoVal = (String) js.executeScript("" +
"var myId; " +
"getCurrentDocumentInfo(\"somestuff\"," +
"function(docId) {" +
"myId = docId;" +
"}" +
");" +
"return myId;");
结果我只得到空值。所以...不知何故我必须 "wait" 回调函数,直到我 return myId。我必须使用 executeAsyncScript 吗?如何使用?我坐在上面几个小时,尝试了不同的东西,但我就是找不到答案。
在此先感谢您的帮助!
对于异步代码,您必须使用 executeAsyncScript
:
JavascriptExecutor js = (JavascriptExecutor) driver;
String docInfoVal = (String) js.executeAsyncScript("" +
"var done = arguments[0]; " +
"getCurrentDocumentInfo(\"somestuff\"," +
"function(docId) {" +
"done(docId);" +
"}" +
");");
您使用 executeAsyncScript
调用的脚本会将回调添加到传递给它的参数列表中。由于您没有向脚本传递任何参数,因此 arguments[0]
包含回调。您的代码必须在完成工作后调用此回调。你给回调的值就是executeAsyncScript
returns.
在上面的代码中,我将对 done
的调用放在一个匿名函数中,但代码可以写得更简洁:
JavascriptExecutor js = (JavascriptExecutor) driver;
String docInfoVal = (String) js.executeAsyncScript("" +
"var done = arguments[0]; " +
"getCurrentDocumentInfo(\"somestuff\", done);");
甚至:
JavascriptExecutor js = (JavascriptExecutor) driver;
String docInfoVal = (String) js.executeAsyncScript(
"getCurrentDocumentInfo('somestuff', arguments[0]);");
尽管这与@Louis said.You 必须事先设置 setScriptTimeout
以使脚本通过的内容几乎相同。
The default timeout for a script to be executed is 0ms. In most cases, including the examples below, one must set the script timeout WebDriver.Timeouts.setScriptTimeout(long, java.util.concurrent.TimeUnit) beforehand to a value sufficiently large enough.
下面是一个例子,我等待 10 秒 return 一个字符串
driver.manage().timeouts().setScriptTimeout(20, TimeUnit.SECONDS);//important
JavascriptExecutor executor = (JavascriptExecutor) driver;
String val = (String) executor.executeAsyncScript(""
+ "var done=arguments[0]; "
+ "setTimeout(function() {"
+ " done('tada');"
+ " }, 10000);");
System.out.println(val);