I am writing Appium (v1.7.1) iOS automation tests where I am chaining a webdriver session and trying loop through the elements to fetch the data.
setFilterOptions: function (driver, loc) {
var chain = driver; //I am assigning the driver to chain
chain = chain
.getFilterElementListCount() //This gives me back the count for elements
.then((count) => {
console.log("Number of Filters - ",count);
for(var i=1; i<=count; i++) {
((i) => {
console.log("Value of i - ", i);
//This gives me the label for each Cell->StaticText
chain = chain
.getElAttribute('label',util.format('//XCUIElementTypeCell[%d]/XCUIElementTypeStaticText[1]', i), 'xpath')
.then((filterTitle, i) => {
console.log("Filter Title - ", filterTitle);
console.log("I value - ", i);
});
})(i);
}
});
return chain;
},
The Console o/p i am getting is -
Number of Filters - 3
Value of i - 1
Value of i - 2
Value of i - 3
The loop iterates but doesn't execute the chain within the for loop. Is there a way for the chain to finish all callback execution before returning it.
Your goal is to return a promise that will resolve once all the work performed in the loop is done. However, that's not what you are doing. Your problem is that you have this:
In order for your code to work, the asynchronous operations would have to assign to
chainbefore thereturnstatement executes. But this is not how asynchronous operations work. When you call any asynchronous method, you are only scheduling the asynchronous operation for future execution. It will execute at some point in the future, but definitely not immediately. In the code you have, you schedule an asynchronous operation and the immediately you returnchain. The value ofchainthat you return cannot be a value that is set in your loop. Your loop has not executed yet.You should do something like the following. The important thing is to create a chain of operations inside the loop and return that chain from the function you pass to
.thenso that the topmost promise resolves to the chain you create in your loop. This way, the promise you return from your method will have to wait for all inner operations to be done before being resolved.Also note that if you use
let iinstead ofvar ifor your loop, you could get rid of that immediately invoked arrow function you have in your loop, which seems to be there only to ensure that the closures inside the loop get sequential values ofi(instead of all executing with the last value ofi).