0

I have a web test code and I don't want to iterate over the rest after i found the item. This code iterate to all item and the finally return. How to resolve this problem, because in the each I don't break!

isItemPresent: function (name) {
            var def = Q.defer();
            Trace.add("Checking the " + name + " inside the menu");
            var count = 0, total = 0, stop = false;
            var listObj = element(by.id(this.MENU_ID)).all(by.tagName("div"));

            listObj.count().then(function (nr) {
                total = nr;
                listObj.each(func);
            });
            var _this = this;          
            var func = function (element) {

                element.getAttribute('class').then(function (classes) {                  
                    count++;
                    if (classes.indexOf(name) !== -1 && !stop) {
                        stop = true;                      
                        element.getAttribute('id').then(function (value) {
                            _this._isItemVisible('', value).then(function (opt) {
                                value = value.match(/(\d+)/g);                            
                                if (opt.success) {
                                   // console.log('------- BREAK --------');
                                    def.resolve({success: true, msg: {index: value[0]}});
                                    Trace.add("Menu item: " + name + " was found in the main menu.");                                  
                                } else {
                                    def.resolve({success: false, msg: {index: value[0]}});
                                    Trace.add("Menu item: " + name + " was not found in the main menu.");
                                }
                            });
                        });
                    } else if (count === total && stop === true) {
                        def.resolve({success: false, msg: {index: 0}});
      Trace.add("Menu item: " + name + " was not found in the main menu.");
                        stop = true;
                    }
                });
            };
            return def.promise;
        };
  • Where exactly are you trying to stop the loop? And, what library is `listObj.each()` from? Does it have a way to stop the loop? You can likely break out of the promise-based stuff by just throwing an exception which the promise library will catch and turn into a promise rejection which you can handle at a higher level. – jfriend00 May 26 '15 at 08:15
  • listObj are contained for example a lot of menu itemes (1000 pice), when I found the item in the eighteenth then BREAK... – Krausz Lóránt Szilveszter May 27 '15 at 05:41
  • I'm asking you what type of object `listObj` is and how does it have a `.each()` method because that is not standard Javascript. And, I'm asking you exactly where in your code you're trying to stop the loop because that effects how you do it? We can't answer your question without understanding these answers. Also, please try to be more timely in your responses or folks will just lose interest in helping. StackOverflow works a lot better if you're' answering questions in less than a few hours rather than waiting almost an entire day. – jfriend00 May 27 '15 at 05:47

1 Answers1

1

Various solutions are available, none of which is particularly obvious. This is the best presentation/discussion that I know of

You might like to consider the very concise Bluebird solution given in this answer, however, sticking with Q, here's a solution based on the "loop" solution in the same answer.

isItemPresent: function (name) {
    var _this = this,
        listObj = element(by.id(this.MENU_ID)).all(by.tagName("div")),
        list = [];

    //Map listObj to the Array `list`, providing a convenient .reduce() method.
    //If listObj has a `.toArray()` method or `.map()` method, then use that in preference.
    listObj.each(function(element) {
        list.push(element);
    });

    // To make func() useful it must return a promise :
    // * fulfilled for success - forcing a "break"
    // * rejected for failure - allowing "continue"
    function func(element) {
        return element.getAttribute('class').then(function(classes) {
            if (classes.indexOf(name) === -1) {
                return Q.reject('class "' + name + '" not found');//"continue"
            } else {
                return element.getAttribute('id').then(function(value) {
                    _this._isItemVisible('', value).then(function(opt) {
                        if(opt.success) {
                            return Q(value.match(/(\d+)/g)[0]);//"break".
                        } else {
                            return Q.reject('class "' + name + '" not visible');//"continue"
                        }
                    });
                });
            }
        });
    };

    // Master routine
    return list.reduce(function(previous, element) {
        return previous.catch(function(error) {
            console.log(error || 'list length is zero'); //optional
            return func(element);
        });
    }, Q.reject(null)).catch(function(error) {
        return Q.reject(-1);//for example
    });
};

Explanation

The master routine builds a .catch() chain seeded with a rejected promise and :

  • as long as func() continues to return a rejected promise, the catch(...) callback ensures that func() is called again for the next element.

  • if func() never hits opt.success, the master routine returns the last rejected promise returned to it (or the seed promise if list has zero length).

  • if/when func() hits opt.success, a promise fulfilled with the required value is returned and the rest of the master routine's promise chain is effectively skipped as there are no success handlers to cause it to do otherwise, and the master routine returns the fulfilled promise that was returned to it.

The final .catch() is just an example. You may want to do something different - whatever is most appropriate for handling failure wherever isItemPresent(name) is called.

Community
  • 1
  • 1
Roamer-1888
  • 19,138
  • 5
  • 33
  • 44