一尘不染

了解Selenium中的执行异步脚本

selenium

我已经使用了很长一段时间了selenium(使用python绑定以及protractor大多数情况下),每次我需要执行javascript代码时,我都使用过execute_script()method。例如,用于滚动页面(python):

driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

或者,要在另一个元素(量角器)内无限滚动:

var div = element(by.css('div.table-scroll'));
var lastRow = element(by.css('table#myid tr:last-of-type'));

browser.executeScript("return arguments[0].offsetTop;", lastRow.getWebElement()).then(function (offset) {
    browser.executeScript('arguments[0].scrollTop = arguments[1];', div.getWebElement(), offset).then(function() {
        // assertions

    });
});

或者,为了获取所有元素属性的字典)(python):

driver.execute_script('var items = {}; for (index = 0; index < arguments[0].attributes.length; ++index) { items[arguments[0].attributes[index].name] = arguments[0].attributes[index].value }; return items;', element)

但是,WebDriver API也具有execute_async_script()我个人未使用过的功能。

它涵盖了哪些用例?什么时候应该execute_async_script()代替常规execute_script()

这个问题是selenium特定的,但与语言无关。


阅读 775

收藏
2020-06-26

共1个答案

一尘不染

这是对这两个API
引用(这是Javadoc,但是功能相同),这是摘录,突出了两者的区别

[executeAsyncScript]在当前选定的框架或窗口的上下文中执行异步JavaScript。与执行同步JavaScript不同,使用此方法执行的脚本必须通过调用提供的回调来显式表示已完成脚本。此回调始终作为最后一个参数注入执行的函数中。

基本上,execSync会阻止硒浏览器正在执行的其他操作,而execAsync不会阻止并在callback完成时调用a 。


由于您已经使用过量角器,因此我将以此为例。量角器用途executeAsyncScriptgetwaitForAngular

在中waitForAngular,量角器需要等到angular宣布所有事件解决为止。您不能使用它,executeScript因为那需要在最后返回一个值(尽管我猜您可以实现一个忙循环,不断轮询角度直到完成)。它的工作方式是量角器提供一个回调,所有事件解决后,Angular会调用该回调,并且需要executeAsyncScript。在这里编码

在中get,量角器需要轮询页面,直到window.angularAngular设置了全局值为止。一种解决方法是driver.wait(function(){driver.executeScript('return window.angular')},5000),但是这种方式,量角器每隔几毫秒就会在浏览器上撞击一次。相反,我们这样做(简化):

functions.testForAngular = function(attempts, callback) {
  var check = function(n) {
    if (window.angular) {
      callback('good');
    } else if (n < 1) {
      callback('timedout');
    } else {
      setTimeout(function() {check(n - 1);}, 1000);
    }
  };
  check(attempts);
};

再次,这是executeAsyncScript因为我们没有立即返回值。在这里编码


总而言之,executeAsyncScript当您关心调用脚本中的返回值时使用,但是该返回值将不会立即可用。如果您无法轮询结果,但必须使用回调或promise(必须将其转换为自己的回调)来获取结果,则这尤其必要。

2020-06-26