【问题标题】:value of the index changes after getText() inside a for loop - PROTRACTOR在 for 循环内 getText() 后索引的值发生变化 - PROTRACTOR
【发布时间】:2018-01-30 09:54:18
【问题描述】:

在下面的代码中,我使用中继器从 ng-repeat 获取值并通过 cat.name 获取列,这给了我一个包含所有猫名的数组。所以我在做一个for循环来获取一个特定的名字,比如说喵,我要存储索引值,这样我就可以验证对应的行,猫的年龄是否等于10。 2 console.log for 循环内的索引的值导致不同的值,第一个范围从 0-10(考虑到数组的长度为 10),下一个总是导致 10。它记录“10”10 次。现在,我无法获取索引来验证相应的行,因为 i 始终为 10。有人可以纠正我哪里出错并用修改后的代码回答我。我想我在链接承诺时出错了

  element(by.repeater(cat in cats).column(cat.name)).then(function(fields) {
    for (var i in fields) {                // promise returns an array fields
      console.log(i);                      // values range from 0 to length of the fields(say 10)
      fields[i].getText().then(function(fieldValue) {
        console.log(i);                    // values are always 10 (i.e the length of the array)
        if(fieldValue === 'Meow') {
          var catAge= element(by.repeater('cat in cats').row(i)).element(by.model('cat.age')); // row(i) always gives the last value
          expect(catAge.getAttribute('value')).toBe('10');
        }
      })
    }
  });

【问题讨论】:

标签: javascript node.js promise protractor


【解决方案1】:

问题来自sn-p下面,第一个console.log()是同步执行的,但是第二个console.log()会异步执行,因为它在getText().then()里面,我们知道所有的Protractor api都是异步并返回一个 Promise。

for (var i in fields) { 
      console.log(i); 
      fields[i].getText().then(function(fieldValue) {
        console.log(i); 

所以上面for循环的实际执行过程应该是这样的:

when i=1
    first console.log() execute done, it print out 1
    fields[i].getText() execute done, it return a Promise,
    and push the promise into Protractor control flow,
    actually getText() not to read the text from page,
    because it's execute async.


when i=2
    first console.log() execute done, it print out 2
    fields[i].getText() execute done, it return a Promise,
    and push the promise into Protractor control flow,
    actually getText() not to read the text from page,
    because it's execute async.

....

when i=10
    the loop end,  
    you get 1, 2 .. 9, 10 printed out
    Protractor control flow get a promise queue
    Now Protractor control flow start to execute the promise queue

    Protractor push out the fist promise in queue
    Important!!! the i=10 now
    fields[i].getText() will be fields[10].getText()
    so you will get fields[10].getText() for 10 times

选项 1) 正如 Jamines 评论所说,使用 javascript 闭包,对您当前的代码进行一些更改

element(by.repeater(cat in cats).column(cat.name)).then(function(fields) {
  for (var i in fields) {
    console.log(i);

    (function(index){ // change part

      fields[index].getText().then(function(fieldValue) {
        console.log(index);  
        if(fieldValue === 'Meow') {
          var catAge= element(by.repeater('cat in cats').row(index)).element(by.model('cat.age'));
          expect(catAge.getAttribute('value')).toBe('10');
        }
      })

    })(i); // change part

  }
});

选项2使用量角器filter()

element(by.repeater(cat in cats).column(cat.name)).then(function(fields) {
  for (var i in fields) {
    console.log(i);
    var matchedIndex = -1;

    fields
      .filter(function(item, index){
        if( matchedIndex > -1) { 
          // means had found the matched one, directly return false to
          // skip read text from page to reduce exection time
          return false;
        }
        else {
          return item.getText().then(function(name){
             if(name === 'Meow') {
               matchedIndex = index;
               return true;
             }
             return false;
          })

        }
      })
      .then(function(){
        console.log('matchedIndex: ' + matchedIndex);  
        var catAge= element(by.repeater('cat in cats').row(matchedIndex)).element(by.model('cat.age'));
        return expect(catAge.getAttribute('value')).toBe('10');
      });
  }
});

【讨论】:

    猜你喜欢
    • 2013-05-11
    • 1970-01-01
    • 2016-06-05
    • 1970-01-01
    • 1970-01-01
    • 2019-05-26
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多