使用带循环的量角器 [英] Using protractor with loops

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

问题描述

循环索引 (i) 不是我在循环中使用量角器时所期望的.

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

症状:

失败:索引越界.试图访问 index:'x' 处的元素,但只有 'x' 个元素

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

索引是静态的并且总是等于最后一个值

Index is static and always equal to the last value

我的代码

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

例如:

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

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

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

推荐答案

发生这种情况的原因是因为量角器使用了 promise.

The reason this is happening is because protractor uses promises.

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

Promises(即 element(by...), element.all(by...))在以下情况下执行它们的 then 函数基础价值准备就绪.这意味着首先安排所有承诺,然后在结果准备就绪时运行 then 函数.

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

发生的情况是 getPromise().then(function() {...}) 立即返回,在 Promise 准备好之前并且没有执行 then.所以首先循环运行 3 次,调度所有 getPromise() 调用.然后,随着 promise 的解析,相应的 then 被运行.

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.

控制台看起来像这样:

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.

那么,你如何在循环中运行量角器?一般的解决方案是关闭.请参阅循环内的 JavaScript 闭包 - 简单实用示例

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

但这不是很好读.幸运的是,您还可以使用量角器函数 filter(fn)get(i)first()last(),以及 expect 被修补以接受承诺的事实,以解决这个问题.

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. 

换句话说,量角器有很多方法来迭代或访问元素i,这样你就不需要使用for循环和i.但是如果你必须使用for循环和i,你可以使用闭包解决方案.

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天全站免登陆