Javascript 在forEach循环中创建承诺并在不嵌套的情况下使用它们
我使用的是SeleniumWebDriver,我通过id获取特定元素。 在获得具有正确id的元素后,我尝试从列表中选择一个具有唯一属性值的元素 我已经设法获得了我需要的价值观,但我对我找到的解决方案不满意 情况:Javascript 在forEach循环中创建承诺并在不嵌套的情况下使用它们,javascript,arrays,foreach,nested,promise,Javascript,Arrays,Foreach,Nested,Promise,我使用的是SeleniumWebDriver,我通过id获取特定元素。 在获得具有正确id的元素后,我尝试从列表中选择一个具有唯一属性值的元素 我已经设法获得了我需要的价值观,但我对我找到的解决方案不满意 情况: var attributeName = "bla"; var id = "icon"; var iconElementsPromise = driver.findElements(By.id(id)); // returns a promise containing an ar
var attributeName = "bla";
var id = "icon";
var iconElementsPromise = driver.findElements(By.id(id)); // returns a promise containing an array with WebElements
解决方案1:嵌套,然后:这看起来非常错误,但它可以工作
iconElementsPromise
.then(function(iconElements) {
iconElements.forEach(function(element, index) {
element.getAttribute(attributeName)
.then(function(attribute) {
console.log("attribute: " + attribute);
});
});
});
解决方案2:只有1个嵌套的然后:看起来更好,但现在我需要创建一个承诺数组,这是确定的。。。但我根本不想筑巢
iconElementsPromise
.then(function(iconElements) {
var promises = [];
iconElements.forEach(function(element, index) {
promises.push(element.getAttribute("tag"));
});
return promises;
})
.then(function(promises) {
Promise.all(promises)
.then(function(attributes) {
console.log("attributes: " + attributes);
});
});
解决方案3:通过返回Promise.all(promises)
我可以保持在相同的索引级别,并且不嵌套然后
s
iconElementsPromise
.then(function(iconElements) {
var promises = [];
iconElements.forEach(function(element, index) {
promises.push(element.getAttribute(attributeName));
});
return promises;
})
.then(function(promises) {
return Promise.all(promises);
})
.then(function(attributes) {
console.log("attributes: " + attributes);
});
解决方案1有2个然后s并获取每个属性
解决方案2和3各有3个,然后
s,并获取属性数组
获取每个属性或仅获取数组是可以的
我确实相信解决方案3或多或少是我想要的。但代码相当长。我觉得必须有一种更好、更可读、更短的方法来获取属性
所以我的问题是:*使用承诺获取属性的最佳方式是什么?
**
示例很受欢迎。使用map
减少一个然后的的简短版本,同时保持可读性
iconElementsPromise
.then(function(iconElements) {
return Promise.all(iconElements.map(function(element){
return element.getAttribute(attributeName);
}));
})
.then(function(attributes) {
console.log("attributes: " + attributes);
});
如果您的目标是选择一个具有唯一属性的元素,那么将该属性包含在定位器中会更容易:
// select with an XPath the first element having an attribute "bla" and a parent with the "icon" id
var element = driver.findElement(By.xpath("id('icon')/*[@bla]"));
// select with a CSS selector the first element having the attribute "bla" and a parent with the "icon" id
var element = driver.findElement(By.cssSelector("#icon > [bla]"));
但是如果您确实想要所有属性,那么一个简单的解决方案是使用webdriver.promise.map
:
var webdriver = require('selenium-webdriver');
var promise = webdriver.promise;
var By = webdriver.By;
var Key = webdriver.Key;
var EC = webdriver.until;
var driver = new webdriver.Builder()
.withCapabilities({'browserName': 'firefox'})
.build();
driver.get('http://stackoverflow.com/');
driver.findElements(By.xpath('//a')).then(function(elts) {
promise.map(elts, function(elt) {
return elt.getAttribute("href");
}).then(function(links) {
console.log(links);
})
});
感谢您提示使用定位器,以前从未使用过,但会将其删除。看起来比在dom中导航更容易。在我的例子中,它实际上应该起作用。如果我理解正确,您可以使用array.map函数交换forEach
循环,并将生成的数组(即Promise)放入Promise.all
,它返回然后打印的属性值。这本书可读性强,篇幅短,谢谢。