Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
161
rated 0 times [  162] [ 1]  / answers: 1 / hits: 15665  / 7 Years ago, thu, february 9, 2017, 12:00:00

I am using Selenium and nodejs to iterate through a html table and match a string from an array to the string in the table cell.



My array might be [Name, Address1, Address2, Address3,...] and the value in tr[1] will try to match with Arr[0], tr[2] with Arr[1] etc.



The html table will have a row for each item in the array, but if there is no data for, say, Address2 then that will not appear.



In that case, tr[3] will find that it cannot match with Arr[3]. Instead of moving to tr[4], I want to see if tr[3] matches with Arr[4], then Arr[5] etc. The items in the table will always be in the same order as the items in the array, so I have no need for any array items unmatched.



I've posted the whole function in case it is relevant, but the issue seems very simply to be that I cannot get i = i - 1 to carry the new value into the next loop iteration.



I have proved that I get into the Else section, and that the value of i - 1 is as I would expect at that point.



var retrieveData = function retrieveData(Arr){

j = 0

driver.findElements(webdriver.By.xpath(//*[@class='table-container'])).then (function(rows){

rowCount = rows.length;
console.log(Row count = + rowCount);

}).then (function(fn){

for (i = 1;i < rowCount + 1; i++){

(function(i){

var element = driver.findElement(webdriver.By.xpath(//div[@class='table-container'][+i+]/div/strong/a));

element.getText().then(function(Type){

var typefromArray = String(Arr[j].split(':')[0]);

if (Type == typefromArray){

// Do something

j = j + 1;

} else {

// Do something

i = i - 1 // My problem looks to be here, but may be in the transfer of this back up to the beginning of the loop
j = j + 1;

}

});

})(i);

};

});

};

module.exports.retrieveData = retrieveData;

More From » node.js

 Answers
285

You are using an IIFE in your for-loop to which you pass the index.
That looks like it was designed to prevent modification of i!



When you do



i = i - 1


at the end of your function, it has absolutely no effect as it only affects the i inside your function.

Here's a good article about variable scopes in JavaScript.



But if you still want to modify i, then one option would be to simply have it be returned by the anonymous function and assigned to the external i variable:



.then (function(fn){
for (i = 1;i < rowCount + 1; i++){
i = (function(i){
var element = driver.findElement(webdriver.By.xpath(//div[@class='table-container'][+i+]/div/strong/a));
element.getText().then(function(Type){
var typefromArray = String(Arr[j].split(':')[0]);
if (Type == typefromArray){
// Do something
j = j + 1;
} else {
// Do something
i = i - 1 // My problem looks to be here, but may be in the transfer of this back up to the beginning of the loop
j = j + 1;
}
});
return i;
})(i);
};


That is the solution to the question you asked.






But I'm pretty sure there will be other problems in your code, as you are using a synchronous loop, yet updating the counter in an asynchronously-called function (the function passed to element.getText().then).



I'd suggest you either study a bit about how to handle asynchronous code in JavaScript (you're using Promises right now) or open a more general question about the bigger problem you are trying to solve as there will be some more design hurdles to overcome.



Here's an example of the kind of patterns you may have to use to handle multiple Promises (not meant to be copy-pasted, used ES2015 for brevity):



.then(function(fn) {
Promise.all(
Array(rowCount).fill(true).map((_, i) => i + 1) // => [1..rowCount]
.map(i => {
const element = driver.findElement(webdriver.By.xpath(//div[@class='table-container'][+i+]/div/strong/a));
return element.getText();
})
// Here we have an array of Promises that we pass to Promise.all
// so we can wait until all promises are resolved before executing
// the following .then
).then(types => types.filter(type => type === typefromArray)
.map(type => { /* doSomething */ });
});

[#59003] Wednesday, February 8, 2017, 7 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
andreguym

Total Points: 125
Total Questions: 112
Total Answers: 103

Location: Wallis and Futuna
Member since Tue, Mar 30, 2021
3 Years ago
;