selenium中的for循环webdriver和nodejs不会异步执行

时间:2018-02-05 05:38:47

标签: node.js selenium-webdriver selenium-chromedriver

我有一个selenium webdriver脚本,没有按预期执行。可能是我不理解承诺和异步。以下是代码 -

var webdriver = require('selenium-webdriver');
var promise = require('selenium-webdriver').promise;
var By = webdriver.By;
var mongoose = require('mongoose');
var config = require('../config/db');
var chrome = require('selenium-webdriver/chrome');
var path = require('chromedriver').path;
var service = new chrome.ServiceBuilder(path).build();
chrome.setDefaultService(service);
var ScrapperModel = require('../models/scrapper-model');
function test1() {
    var dbObj = new ScrapperModel({ name: 'Tom' });
    dbObj.save(function(err, doc){
        if(err){
            console.log("Error saving object in schema"+err);
        }
    });

    var browser = new webdriver.Builder().usingServer().withCapabilities({ 'browserName': 'chrome' }).build();
    browser.get('https://www.example.com/').then(function () {
        return browser.getTitle();
    }
    ).then(function (title) {
        console.log("Title is" + title);
    }).then(function(){
        return browser.findElement(By.id('orderNumber')).sendKeys('12345');  
    }).then(function(){
        return browser.findElement(By.id('orderEmail')).sendKeys('test@test.com');   
    }).then(function(){
        return browser.findElement(By.id('postalCode')).sendKeys('46204');   
    }).then(function(){
        return browser.findElement(By.name('findorder')).click();  
    }).then(function(){
        return browser.findElements(By.xpath('//*[@class="order-shipment-table"]'));
    }).then(function(elements){
        console.log("****"+elements.length);
        elements.forEach(function(element){
            //console.log("---"+element.getAttribute('class'));
            return browser.findElement(By.id('someid'));
            anotherFunction(browser);
            //console.log("++"+element.getAttribute('class'));
        });     

    }).then(function () {
        console.log("closing");
        return browser.close();
    })
        .catch(function (err) {
            console.log("err" + err);
            return browser.close();
        });
};

function anotherFunction(browser){
consolelog("inside function");
}
module.exports.test1 = test1;

这里,除了我需要使用的for循环之外,代码工作正常。我正在使用browser.findElement的页面上有一些webelements然后需要使用for循环执行它们并且基于某些条件需要在同一文件中调用函数以使用浏览器对象执行更多执行。如果我使用forloop,它立即执行,内部代码仅适用于最后一个值,即如果for循环应该从1到5执行,它将正确打印1到5但脚本由于异步行为只选择5。我尝试使用forEach如下,但它返回我 - (node:15420) UnhandledPromiseRejectionWarning: Unhandled promise rejection (reje ction id: 1): NoSuchSessionError: no such session 执行完所有步骤并关闭浏览器后。如果我重新开始这个循环,一切正常。

有什么方法可以在for循环中执行这些selenium webdriver命令,for循环等待下一次迭代直到命令不执行。这些命令正在回归我相信的承诺。

如果我使用如下的forloop -

.then(function(){
    for (var row = 2; row < count; row++) {
        return driver.findElement(By.id('itemid')).then(function(order){
            console.log("++++"+row);
            return order.findElement(By.xpath('//table/tbody/tr[' + row+ ']/td[2]/span[1]')).getText();
        }).then(function(productName){
            console.log("i am ok .."+productName);
       });          
    }
}).then(function(){
    return driver.close();
})

它只对行的最后一个值执行driver.findElement命令。如果我将第一个return语句放在这个for循环中(如上所述),它只对row = 2执行并关闭浏览器。

1 个答案:

答案 0 :(得分:0)

以下代码在同步循环中是异步的:

for (var row = 2; row < count; row++) {
        return driver.findElement(By.id('itemid')).then(function(order){
            console.log("++++"+row);
            return order.findElement(By.xpath('//table/tbody/tr[' + row+ ']/td[2]/span[1]')).getText();
        }).then(function(productName){
            console.log("i am ok .."+productName);
       });          
}

实际发生的是当循环开始时,row = 2的值然后调用异步函数driver.findElement。回调进入队列,然后行值更新为3,同样的事情发生。

现在当触发回调时(异步任务完成时),行的值是最后一个值。

您可以保留单独的行数组,并将订单映射到该行。请尝试Promise.all()。

const P = require('bluebird');
const _ = require('lodash');
const rows = [2, 3, 4, 5];

const exampleFunction = (rows) => {
    return P.try(() => {
        const promises = _.map(rows, (e) => {
        return driver.findElement(e);
    });

    return P.all(promises);
    }).then((results) => {
        return P.all(_.map(results, (e, index) => {
            return e.findElement(By.xpath('//table/tbody/tr[' + rows[index]+ ']/td[2]/span[1]')
        }));
    });
}