最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

node.js - Javascript: increment counter variable inside loop - Stack Overflow

programmeradmin0浏览0评论

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;

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;
Share Improve this question asked Feb 9, 2017 at 15:55 user7540600user7540600 331 gold badge1 silver badge3 bronze badges 3
  • 1 You have the i = i - 1 inside the IIFE. You also could use i-- and j++. – Aureliano Far Suau Commented Feb 9, 2017 at 16:02
  • Hi, thanks for the quick response! I only want to decrease the counter if the string doesn't match (i.e. the If statement returns False). How can I keep the i = i - 1(or i--) outside the Else? – user7540600 Commented Feb 9, 2017 at 16:11
  • You are shadowing the scope of the i in the (function(i){ declaration. – Sunshine Commented Feb 9, 2017 at 16:25
Add a ment  | 

1 Answer 1

Reset to default 5

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 overe.

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 */ });
});
发布评论

评论列表(0)

  1. 暂无评论