【问题标题】:Selenium and asynchronous JavaScript callsSelenium 和异步 JavaScript 调用
【发布时间】:2015-09-21 09:56:20
【问题描述】:

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

1. var myId;
2. getSomeIdStuffInfo("somestuff",function(docId)(myId = docId));
3. return myId;

如果我一步一步输入这行,我很容易得到正确的值 myId。但是,当然,如果我尽可能快地执行这三行,我会得到 null 作为返回值,因为当我返回 myId 时回调函数还没有完成。 SOOOO .. 如果我像这样使用硒:

JavascriptExecutor js = (JavascriptExecutor) driver; 
    String docInfoVal = (String) js.executeScript("" +
            "var myId; " +
            "getCurrentDocumentInfo(\"somestuff\"," +
                "function(docId) {" +
                    "myId = docId;" +
                "}" +
            ");" +
            "return myId;");

我只得到 null 作为结果。所以......不知何故,我必须“等待”回调函数,直到我返回 myId。我是否必须使用 executeAsyncScript 以及如何使用?我坐在上面几个小时,尝试了不同的东西,但我就是找不到答案。

提前感谢您的帮助!

【问题讨论】:

    标签: javascript function selenium asynchronous callback


    【解决方案1】:

    尽管这与@Louis 所说的几乎相同。您必须事先设置setScriptTimeout 才能使脚本通过。

    要执行的脚本的默认超时时间是 0 毫秒。在大多数情况下, 包括下面的例子,必须设置脚本超时 WebDriver.Timeouts.setScriptTimeout(long, 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);
    

    【讨论】:

    • 您为我节省了数小时的无脑调试!谢谢!
    【解决方案2】:

    对于异步代码你必须使用executeAsyncScript:

    JavascriptExecutor js = (JavascriptExecutor) driver; 
    String docInfoVal = (String) js.executeAsyncScript("" +
            "var done = arguments[0]; " +
            "getCurrentDocumentInfo(\"somestuff\"," +
                "function(docId) {" +
                    "done(docId);" +
                "}" +
            ");");
    

    您使用executeAsyncScript 调用的脚本将在传递给它的参数列表中添加一个回调。由于您没有向脚本传递任何参数,因此 arguments[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]);");
    

    【讨论】:

    • 在所有示例中,这似乎很容易理解
    • 感谢您的简单解释,它有效,更重要的是,我想我明白了:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-25
    • 2012-02-25
    • 2020-03-08
    • 1970-01-01
    • 2016-03-07
    • 2016-08-19
    • 2021-05-28
    相关资源
    最近更新 更多