问题
I'm using Protractor and cucumber framework; how do I break out of a .filter or .map loop? I do not want to continue to iterate further if I found a match!
Page.prototype.getElementByKey = function (key) {
var foundElement = null;
return someElement.all(by.css('.someClass')).map(function (rawItem, index) {
var itemObject = new ItemObjectClass(rawItem);
return itemObject.getItemKey().then(function (foundItemKey) {
var matched = String(foundItemKey).trim() === String(key).trim();
console.log(' Matched: { ' + matched + ' } index {'+index+'}');
//if we have a match break out of the .filter function
if (matched) {
foundElement = itemObject;
throw new Error("Just our way of breaking out of .filter() above");
}
});
}).then(function () {
//callback
throw new Error('\n!!!!!Callback should not be called;
this means that we could not find an element that matched the passed in key above');
}, function (error) {
//error
console.log('\n*******************errorCallback was called; '+error);
return foundElement;
});
};
The above code finds the element but continues to iterate until the end instead of stopping when there's a match and breaking out by calling the errorCallback function.
Given that .map function returns "a promise that resolves to an array of values returned by the map function" http://www.protractortest.org/#/api?view=ElementArrayFinder.prototype.map, I'm taking advantage of the fact that a promise will call its errCallback if the promise cannot be resolved.
By throwing an a fake error, the errorCallback should be called and thereby break out of the .map loop.
Unfortunately, it successfully throws the error but continues with the loop instead of breaking out. I know that because when I
console.log("boolean "+matched+" and index "+index);
I get this:
matched: false index: 0
matched: false index: 1
matched: true index 2 //it should have stopped here since matched = true
matched false index 3 // this should NOT have printed
so breaking out isn't working any ideas?
回答1:
You are returning a single element, so .reduce
would be preferable.
Here is a usage example to return the first link where the text is "mylink":
var link = element.all(by.css('a')).reduce(function (result, elem, index) {
if(result) return result;
return elem.getText().then(function(text){
if(text === "mylink") return elem;
});
}).then(function(result){
if(!result) throw new Error("Element not found");
return result;
});
回答2:
What i understood from your post is, you would like to exit loop(iterate) when find a match element.
If yes, then better go with .filter() method. As it iterates on all available list of element finders and returns when a match finds.
Code Snippet:
element.all(by.css('.items li')).filter(function(elem, index) {
return elem.getText().then(function(text) {
if(text === 'RequiredElementFind'){
return ele;//return matched element
};
});
}).click();//only matched element comes from the loop do what would you like
to do
来源:https://stackoverflow.com/questions/38777577/breaking-out-of-a-protractor-filter-or-map-loop