han*_*uan 27 promise angularjs selenium-webdriver protractor
循环索引(i)不是我在循环中使用Protractor时所期望的.
症状:
失败:索引越界.试图访问索引处的元素:'x',但只有'x'元素
要么
索引是静态的,始终等于最后一个值
我的代码
for (var i = 0; i < MAX; ++i) {
getPromise().then(function() {
someArray[i] // 'i' always takes the value of 'MAX'
})
}
Run Code Online (Sandbox Code Playgroud)
例如:
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.
})
}
Run Code Online (Sandbox Code Playgroud)
要么
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"
}
})
}
Run Code Online (Sandbox Code Playgroud)
要么
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"
}
})
}
})
Run Code Online (Sandbox Code Playgroud)
han*_*uan 37
发生这种情况的原因是因为量角器使用了承诺.
阅读https://github.com/angular/protractor/blob/master/docs/control-flow.md
当底层值准备就绪时element(by...),Promises(即element.all(by...))执行它们的then功能.这意味着所有的承诺都是先安排then好的,然后在结果准备就绪时运行这些功能.
当你运行这样的事情:
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);
Run Code Online (Sandbox Code Playgroud)
会发生什么是getPromise().then(function() {...})在promise准备就绪之前立即返回并且不执行内部函数then.所以首先循环运行3次,安排所有getPromise()调用.然后,当承诺解决时,then运行相应的s.
控制台看起来像这样:
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.
Run Code Online (Sandbox Code Playgroud)
那么,你如何在循环中运行量角器?一般的解决方案是关闭.请参阅循环内的JavaScript闭包 - 简单的实际示例
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);
Run Code Online (Sandbox Code Playgroud)
但这并不好看.幸运的是,你还可以用量角器功能filter(fn),get(i),first(),last(),和这样一个事实expect修补采取的承诺,来处理这个.
回到前面提供的示例.第一个例子可以改写为:
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.
}
Run Code Online (Sandbox Code Playgroud)
第二个和第三个例子可以改写为:
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.
Run Code Online (Sandbox Code Playgroud)
换句话说,量角器有许多方法可以迭代或访问元素,i因此您不需要使用for循环和i.但是如果你必须使用for循环i,你可以使用闭包解决方案.
| 归档时间: |
|
| 查看次数: |
42608 次 |
| 最近记录: |