在for循环中链接的WebDriver只迭代循环而不执行回调

时间:2017-11-15 18:47:56

标签: javascript promise mocha appium magellan-nightwatch

我正在编写Appium(v1.7.1)iOS自动化测试,我正在链接webdriver会话并尝试循环遍历元素以获取数据。

setFilterOptions: function (driver, loc) {
    var chain = driver;                  //I am assigning the driver to chain
    chain = chain
         .getFilterElementListCount()    //This gives me back the count for elements
         .then((count) => {
            console.log("Number of Filters - ",count);  

            for(var i=1; i<=count; i++) {
              ((i) => {
                console.log("Value of i - ", i);
                //This gives me the label for each Cell->StaticText
                chain = chain
                      .getElAttribute('label',util.format('//XCUIElementTypeCell[%d]/XCUIElementTypeStaticText[1]', i), 'xpath')                           
                      .then((filterTitle, i) => {
                            console.log("Filter Title - ", filterTitle);
                            console.log("I value - ", i);
                      });
              })(i);
            }
         });
  return chain;
},    

The Console o/p i am getting is - 
Number of Filters -  3
Value of i -  1
Value of i -  2
Value of i -  3

循环迭代但不在for循环中执行链。链是否有办法在返回之前完成所有回调执行。

1 个答案:

答案 0 :(得分:0)

您的目标是返回一个承诺,该承诺将在 all 完成循环中完成的工作后解析。但是,这不是你在做什么。你的问题是你有这个:

  chain = chain.//
                // Bunch of asynchronous operations, some of which assign 
                // to the variable `chain`.
                //
  return chain;

为了使代码正常工作,异步操作必须在执行chain语句之前分配给return 。但这不是异步操作的工作原理。当您调用任何异步方法时,您只是调度异步操作以供将来执行。它将在未来的某个时刻执行,但绝对不会立即执行。在您拥有的代码中,您可以安排异步操作,并立即返回chain您返回的chain的值不能是您在循环中设置的值。您的循环尚未执行。

您应该执行以下操作。重要的是在循环内创建一个操作链,并从您传递给.then的函数中返回该链,以便最顶层的promise解析为您在循环中创建的链。这样,从方法返回的承诺必须等待所有内部操作在解决之前完成。

setFilterOptions: function (driver, loc) {
    return driver
         .getFilterElementListCount()    //This gives me back the count for elements
         .then((count) => {
            var chain = Promise.resolve();
            console.log("Number of Filters - ",count);  

            for(var i=1; i<=count; i++) {
              ((i) => {
                console.log("Value of i - ", i);
                //This gives me the label for each Cell->StaticText
                chain = chain
                      .getElAttribute('label',util.format('//XCUIElementTypeCell[%d]/XCUIElementTypeStaticText[1]', i), 'xpath')                           
                      .then((filterTitle, i) => {
                            console.log("Filter Title - ", filterTitle);
                            console.log("I value - ", i);
                      });
              })(i);
            }

            // Return your promise!                
            return chain;
         });
},    

另请注意,如果您在循环中使用let i而不是var i,则可以摆脱循环中立即调用的箭头函数,这似乎只是为了确保循环内的闭包获得i的连续值(而不是使用i的最后一个值执行所有。)