如何从Selenium Webdriver获取异步JavaScript响应

10
我们在网站上添加了一个异步JavaScript调用。我正在尝试让Selenium Webdriver等待来自该调用的响应。 监听器如下:
$(document).on("application:subapp:rendered", function(){console.log("foo");});

我的webdriver代码(Python):

driver.set_script_timeout(30)
response =  driver.execute_async_script("$(document).on(\"application:subapp:rendered\", function(){return \"foo\";});"

下一步我执行页面应该会返回"foo"

但是我的回应是这样的...

TimeoutException: Message: 异步脚本超时:30秒内未接收到结果 (Session info: chrome=41.0.2272.118) (Driver info: chromedriver=2.11.298604 (75ea2fdb5c87f133a8e1b8da16f6091fb7d532 1e),platform=Windows NT 6.1 SP1 x86_64)

2个回答

12

当您调用execute_async_script时,Selenium会将回调函数作为最后一个参数传递给JavaScript代码,您必须调用该回调函数以指示异步代码已执行完成。如果您在调用execute_async_script时未传递参数,则可以在JavaScript中通过arguments[0]访问它。无论您向此回调函数传递什么值,都将成为您的execute_async_script返回的值,因此:

response = driver.execute_async_script("""
    var done = arguments[0];
    $(document).one('application:subapp:rendered', 
        function(){
           done('foo');
    });
""")
在上面的代码中,我将回调函数指定为done。这只是我喜欢这样做的方式。请注意,通过调用done("foo")来设置response的值。

还要注意,我使用的是.one()而不是.on()。我发现Selenium(至少到2.45版本)永远不会认为为execute_async_script创建的旧回调已经“过时”,因此,如果在你上面的JavaScript执行完成后,还有任何机会再次发生你的事件,那么它将再次调用回调函数,并且Selenium将再次执行调用。如果此时恰好有另一个execute_async_script正在运行,那么这个虚假的调用将使您的其他execute_async_script调用以返回值“foo”终止。我曾经在我的测试套件中遇到过这种情况,它导致非常奇怪的失败。


请参考以下已经翻译好的内容:https://dev59.com/p14c5IYBdhLWcg3wUI4N#28066902 - kaliiiiiiiii

2

arguments[0]用作回调函数:

driver.execute_async_script("""
    $(document).on('application:subapp:rendered', arguments[0]);
""")

参见(有助于理解):


@user3249517 谢谢,请接受Louis的答案 - 它更加详细和完整。 - alecxe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接