我使用Selenium和nodejs遍历html表并将数组中的字符串与表格单元格中的字符串匹配。
我的阵列可能是["姓名","地址1","地址2","地址3和#34;,...]和tr [1]中的值将尝试与Arr [0]匹配,tr [2]与Arr [1]等匹配。
html表对于数组中的每个项都有一行,但是如果没有数据,比如说Address2则不会出现。
在这种情况下,tr [3]会发现它与Arr [3]不匹配。而不是移动到tr [4],我想看看tr [3]是否与Arr [4]匹配,然后是Arr [5]等。表中的项目将始终与数组中的项目的顺序相同,所以我不需要任何数组项目"无与伦比的#34;。
我已经发布了整个功能,以防它相关,但问题似乎很简单,因为我无法得到" i = i - 1"将新值传递到下一个循环迭代中。
我已经证明我进入了Else部分,并且i - 1的值正如我期望的那样。
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;
答案 0 :(得分:5)
您在for
循环中使用IIFE,并将索引传递给该循环。
这似乎是为了防止修改i
!
当你这样做时
i = i - 1
在您的功能结束时,它完全没有效果,因为它只影响您的功能中的i
。
Here's a good article关于JavaScript中的变量范围。
但是如果你仍然想要修改i
,那么一个选项就是让它由匿名函数返回并分配给外部i
变量:
.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);
};
这就是你问的问题的解决方案。
但我很确定您的代码中会出现其他问题,因为您正在使用同步循环,但在异步调用的函数(传递给element.getText().then
的函数)中更新计数器。
我建议您研究一下如何在JavaScript中处理异步代码(您现在正在使用Promises)或者打开一个关于您正在尝试的更大问题的更一般性问题要解决,因为还有一些设计障碍需要克服。
以下是您可能必须使用的一种模式示例,用于处理多个Promise(不是要复制粘贴,为简洁起见使用ES2015):
.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 */ });
});