用量角器与循环 [英] Using protractor with loops

查看:218
本文介绍了用量角器与循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

循环指数( I )是不是我期待,当我在一个循环中使用量角器。

症状:


  

失败:索引越界。试图在索引访问元素:X,但也有只有'x'的元素



  

指数是静态的和总是等于最后值


我的code

 为(VAR I = 0; I< MAX; ++ I){
  getPromise()。然后(函数(){
    的someArray [I] //'我'总是'最大'的值
  })
}

例如:

  VAR预期= ['expect1','expect2','expect3'];
VAR埃尔斯= element.all(by.css('选择'));
对于(VAR I = 0; I< expected.length ++我){
  els.get(我).getText()。然后(函数(文本){
    期待(文本).toEqual(预期[I]); //错误:`i`为3。
  })
}

 厄尔斯VAR = element.all(by.css('选择'));
为(变量I = 0;我3; ++ⅰ){
  els.get(我).getText()。然后(函数(文本){
    如果(文字==='应该单击'){
      els.get(ⅰ)。点击(); //失败,失败:索引超出必然试图索引来访问元素:3,但只有3个元素
    }
  })
}

 厄尔斯VAR = element.all(by.css('选择'));
els.then(功能(rawelements){
  对于(VAR I = 0; I< rawelements.length ++我){
    rawelements [I] .getText()。然后(函数(文本){
      如果(文字==='应该单击'){
        rawelements [I]。点击(); //失败,失败:索引超出必然试图索引来访问元素:'rawelements.length,但只有rawelements.length元素
      }
    })
  }
})


解决方案

这是发生的原因是因为量角器使用的承诺。


  

读<一个href=\"https://github.com/angular/protractor/blob/master/docs/control-flow.md\">https://github.com/angular/protractor/blob/master/docs/control-flow.md


承诺(即元素(由...) element.all(由...))当潜在价值准备好执行他们的然后功能。这意味着,所有的承诺都是第一次计划,然后然后根据结果准备就绪函数运行。

当您运行是这样的:

 为(VAR I = 0;我3; ++ I){
  的console.log(1)我是:'我);
  getPromise()。然后(函数(){
    的console.log('2)我是:'我);
    的someArray [I] //'我'总是值3
  })
}
的console.log('*完成循环i的:'我);

什么情况是, getPromise()。然后(函数(){...})立即返回,在此之前的承诺已准备就绪,但不执行内部功能然后。所以第一循环通过3次运行,调度所有的 getPromise()来电。那么,作为承诺解决,相应的然后 s的运行。

控制台会是这个样子:

  1)i为:0 //时间表第一个`getPromise()`
1)i是:每秒1 //时间表`getPromise()`
1)i是:2 //时间表第三`getPromise()`
*完成循环。我是:3
2)我是:3 //第一个`then`功能运行,但我现在已经是3。
2)我是:3 //第二个`then`功能运行,但我现在已经是3。
2)我是:3 //第三`then`功能运行,但我现在已经是3。

那么,你怎么跑在循环量角器?
一般的解决方法是关闭。见<一href=\"http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example\">JavaScript闭包内环路 - 简单实用的例子

 为(VAR I = 0;我3; ++ I){
  的console.log(1)我是:'我);
  VAR FUNC =(函数(){
    变种J =;
    返回功能(){
      的console.log('2)j是:',j)的;
      的someArray [J] //'J'需要的0..2值
    }
  })();
  getPromise(),然后(FUNC)。
}
的console.log('*完成循环i的:'我);

但是,这是不是很好看。幸运的是,你还可以用量角器功能过滤器(FN) GET(我)第一个()最后一个(),而事实上,期望修补拿承诺,要处理这个问题。

让我们回到前面提供的例子。第一实例可以重写为:

  VAR预期= ['expect1','expect2','expect3'];
VAR埃尔斯= element.all(by.css('选择'));
对于(VAR I = 0; I&LT; expected.length ++我){
  期待(els.get(I).getText())toEqual(预期由[i]); //注意,我不再是一个'then`功能,并采取正确的价值观。
}

第二和第三个实施例可以被改写为:

 厄尔斯VAR = element.all(by.css('选择'));
els.filter(功能(ELEM){
  返回elem.getText()。然后(函数(文本){
    返回文本===应该单击';
  });
})点击();
//注意这里我们先用一个过滤器来选择合适的元素,并使用的事实,像`click`动作可以作用在阵列上点击所有匹配的元素。其结果是,我们可以停止使用一个for循环干脆。

在换句话说,量角器有很多方法来遍历或访问元素 I ,这样你就不需要使用for循环和 I 。但是,如果你必须使用循环和 I ,您可以使用封闭的解决方案。

Loop index (i) is not what I'm expecting when I use Protractor within a loop.

Symptoms:

Failed: Index out of bound. Trying to access element at index:'x', but there are only 'x' elements

or

Index is static and always equal to the last value

My code

for (var i = 0; i < MAX; ++i) {
  getPromise().then(function() {
    someArray[i] // 'i' always takes the value of 'MAX'
  })
}

For example:

var expected = ['expect1', 'expect2', 'expect3'];
var els = element.all(by.css('selector'));
for (var i = 0; i < expected.length; ++i) {
  els.get(i).getText().then(function(text) {
    expect(text).toEqual(expected[i]); // Error: `i` is always 3. 
  })
}

or

var els = element.all(by.css('selector'));
for (var i = 0; i < 3; ++i) {
  els.get(i).getText().then(function(text) {
    if (text === 'should click') {
      els.get(i).click(); // fails with "Failed: Index out of bound. Trying to access element at index:3, but there are only 3 elements"
    }
  })
}

or

var els = element.all(by.css('selector'));
els.then(function(rawelements) {
  for (var i = 0; i < rawelements.length; ++i) {
    rawelements[i].getText().then(function(text) {
      if (text === 'should click') {
        rawelements[i].click(); // fails with "Failed: Index out of bound. Trying to access element at index:'rawelements.length', but there are only 'rawelements.length' elements"
      }
    })
  }
})

解决方案

The reason this is happening is because protractor uses promises.

Read https://github.com/angular/protractor/blob/master/docs/control-flow.md

Promises (i.e. element(by...), element.all(by...)) execute their then functions when the underlying value becomes ready. What this means is that all the promises are first scheduled and then the then functions are run as the results become ready.

When you run something like this:

for (var i = 0; i < 3; ++i) {
  console.log('1) i is: ', i);
  getPromise().then(function() {
    console.log('2) i is: ', i);
    someArray[i] // 'i' always takes the value of 3
  })
}
console.log('*  finished looping. i is: ', i);

What happens is that getPromise().then(function() {...}) returns immediately, before the promise is ready and without executing the function inside the then. So first the loop runs through 3 times, scheduling all the getPromise() calls. Then, as the promises resolve, the corresponding thens are run.

The console would look something like this:

1) i is: 0 // schedules first `getPromise()`
1) i is: 1 // schedules second `getPromise()`
1) i is: 2 // schedules third `getPromise()`
*  finished looping. i is: 3
2) i is: 3 // first `then` function runs, but i is already 3 now.
2) i is: 3 // second `then` function runs, but i is already 3 now.
2) i is: 3 // third `then` function runs, but i is already 3 now.

So, how do you run protractor in loops? The general solution is closure. See JavaScript closure inside loops – simple practical example

for (var i = 0; i < 3; ++i) {
  console.log('1) i is: ', i);
  var func = (function() {
    var j = i; 
    return function() {
      console.log('2) j is: ', j);
      someArray[j] // 'j' takes the values of 0..2
    }
  })();
  getPromise().then(func);
}
console.log('*  finished looping. i is: ', i);

But this is not that nice to read. Fortunately, you can also use protractor functions filter(fn), get(i), first(), last(), and the fact that expect is patched to take promises, to deal with this.

Going back to the examples provided earlier. The first example can be rewritten as:

var expected = ['expect1', 'expect2', 'expect3'];
var els = element.all(by.css('selector'));
for (var i = 0; i < expected.length; ++i) {
  expect(els.get(i).getText()).toEqual(expected[i]); // note, the i is no longer in a `then` function and take the correct values.
}

The second and third example can be rewritten as:

var els = element.all(by.css('selector'));
els.filter(function(elem) {
  return elem.getText().then(function(text) {
    return text === 'should click';
  });
}).click(); 
// note here we first used a 'filter' to select the appropriate elements, and used the fact that actions like `click` can act on an array to click all matching elements. The result is that we can stop using a for loop altogether. 

In other words, protractor has many ways to iterate or access element i so that you don't need to use for loops and i. But if you must use for loops and i, you can use the closure solution.

这篇关于用量角器与循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆