Selenium和异步JavaScript调用

Selenium和异步JavaScript调用,javascript,function,selenium,asynchronous,callback,Javascript,Function,Selenium,Asynchronous,Callback,我对Selenium和JavaScript回调函数非常陌生,我有一个自己无法解决的大问题。我需要一个使用JavaScript的指定变量。如果我用GoogleChrome打开页面并使用控制台输入JavaScript代码,我可以使用如下方式获取变量: 1. var myId; 2. getSomeIdStuffInfo("somestuff",function(docId)(myId = docId)); 3. return myId; JavascriptExecutor js = (Javas

我对Selenium和JavaScript回调函数非常陌生,我有一个自己无法解决的大问题。我需要一个使用JavaScript的指定变量。如果我用GoogleChrome打开页面并使用控制台输入JavaScript代码,我可以使用如下方式获取变量:

1. var myId;
2. getSomeIdStuffInfo("somestuff",function(docId)(myId = docId));
3. return myId;
JavascriptExecutor js = (JavascriptExecutor) driver; 
    String docInfoVal = (String) js.executeScript("" +
            "var myId; " +
            "getCurrentDocumentInfo(\"somestuff\"," +
                "function(docId) {" +
                    "myId = docId;" +
                "}" +
            ");" +
            "return myId;");
如果我一步一步地输入这些行,我很容易得到正确的值myId。但是,当然,如果我尽可能快地执行这三行,我会得到null作为返回值,因为当我返回myId时回调函数还没有完成。太好了。。如果我像这样使用selenium:

1. var myId;
2. getSomeIdStuffInfo("somestuff",function(docId)(myId = docId));
3. return myId;
JavascriptExecutor js = (JavascriptExecutor) driver; 
    String docInfoVal = (String) js.executeScript("" +
            "var myId; " +
            "getCurrentDocumentInfo(\"somestuff\"," +
                "function(docId) {" +
                    "myId = docId;" +
                "}" +
            ");" +
            "return myId;");
结果我只得到null。所以不知何故,我不得不“等待”回调函数,直到我返回myId。我必须使用executeAsyncScript吗?如何使用?我在上面坐了好几个小时,尝试了不同的方法,但我就是找不到答案


提前感谢您的帮助

对于异步代码,必须使用
executeAsyncScript

JavascriptExecutor js = (JavascriptExecutor) driver; 
String docInfoVal = (String) js.executeAsyncScript("" +
        "var done = arguments[0]; " +
        "getCurrentDocumentInfo(\"somestuff\"," +
            "function(docId) {" +
                "done(docId);" +
            "}" +
        ");");
使用
executeAsyncScript
调用的脚本将在传递给它的参数列表中添加回调。由于没有向脚本传递参数,因此
参数[0]
包含回调。代码必须在完成回调后调用它。您给回调的值是
executeAsyncScript
返回的值

在上面的代码中,我将调用
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所说的几乎相同,但你必须事先设置脚本才能通过

要执行的脚本的默认超时为0毫秒。在大多数情况下, 包括下面的示例,必须设置脚本超时 WebDriver.Timeouts.setScriptTimeout(长, java.util.concurrent.TimeUnit)的值 足够大

下面是一个示例,我等待10秒返回一个字符串

  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);

在所有的例子中,这似乎很容易理解谢谢你的简单解释,它是有效的,更重要的是,我想我明白了:)你帮我节省了几个小时的无意识调试!非常感谢。