Der Grund, warum dies geschieht, ist, weil Winkelmesser Versprechen verwendet.
lesen https://github.com/angular/protractor/blob/master/docs/control-flow.md
Promises (d.h. element(by...)
, element.all(by...)
) führen ihre then
Funktionen, wenn der Basiswert bereit wird. Was das bedeutet ist, dass alle Versprechen zuerst geplant werden und dann die then
Funktionen ausgeführt werden, wie die Ergebnisse bereit werden.
Beschreibung Wenn Sie so etwas wie dieses:
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);
Was passiert, ist, dass getPromise().then(function() {...})
kehrt sofort, bevor das Versprechen bereit ist, und ohne die Funktion innerhalb des then
ausführt. Also läuft die Schleife zuerst dreimal durch und plant alle getPromise()
Anrufe. Dann, als die Versprechen sich auflösen, werden die entsprechenden then
s ausgeführt.
Die Konsole würde wie folgt aussehen:
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.
Also, wie Sie laufen Sie Winkelmesser in Schleifen? Die allgemeine Lösung ist Schließung. Siehe 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);
Aber das ist nicht so schön zu lesen. Glücklicherweise können Sie auch Winkelmesserfunktionen verwenden filter(fn)
, get(i)
, first()
, last()
, und die Tatsache, dass expect
gepatcht ist, um Versprechen zu nehmen, damit umzugehen.
Zurück zu den oben angegebenen Beispielen.Das erste Beispiel umgeschrieben werden kann als:
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.
}
Die zweite und dritte Beispiel kann wie folgt umgeschrieben werden:
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.
Mit anderen Worten, hat Winkelmesser viele Möglichkeiten iterieren oder Zugriffselement i
, so dass Sie don 't müssen for-Schleifen und i
verwenden. Aber wenn Sie For-Schleifen und i
verwenden müssen, können Sie die Verschlusslösung verwenden.
Danke für die Mühe - aber das ist das klassische Closure-Loop-Problem. –
@BenjaminGruenbaum Ja das ist das klassische Closure-Loop-Problem, und ich verweisen http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example in der Antwort. Allerdings habe ich das aus zwei Gründen geöffnet. 1) viele Menschen nicht erkennen, die Korrelation zwischen den beiden, weil einige Menschen nicht verstehen ElementFinders Versprechen zurück und 2) Schließung ist nicht die beste Lösung für Winkelmesser als es gibt Winkelmesser spezifische Lösungen dafür - siehe Antwort – hankduan
Die Spannung ist bringt mich um! Welche zwei Gründe? –