Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

selenium - Breaking out of a Protractor .filter() or .map() loop

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('
!!!!!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('
*******************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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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;
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...