Reputation: 1375
I am using protractor to run e2e test cases. All protractor calls are async calls. The below code is a protractor code :
gridRow.then(function (rows) {
for (var index = 0; index < rows.length; index++) {
console.log(index); -------------------- 1
rows[index].all(by.className('ui-grid-cell-contents ng-scope')).get(1).getText().then(function (text) {
console.log(index); ----------------- 2
if (text.toUpperCase().replace(/ |-/g, '') === 'BRANCHONE') {
console.log(index); -------------- 3
}
});
}
});
The rows.length = 2 in this case. Console.log at 1 outputs 0 and 1 as expected but the console.log at 2 and 3 outputs as 2, because the then calls are async.Since the async calls run parallely , in the mean time the value of index gets updated to 2(index++).
Any idea about how to track that sync variale(index) inside my async calls?
Upvotes: 1
Views: 96
Reputation: 3854
What I usually do is wrap the callback function in another function to capture the sync variable in a new scope. To illustrate, what you have right now is effectively:
var callback = function(text) {
// use text and index...
};
async_call(...).then(callback);
The problem is of course that the index
variable (which is captured by the callback function) changes after the callback gets created. Because the callback function uses a closure to capture a reference to that value, it ends up seeing the changed value.
To capture the value of index
during that particular loop iteration, you can create a new scope, with a new variable that doesn't get changed. Basically you create another function and call it with the current index
, and the parameter for the function captures that specific value. Then you can have that function return another function that you use as your callback. Example code to clear up that horrible description:
function createCallback(curIndex) {
return function(text) {
// use text and curIndex...
};
}
//...
var callback = createCallback(index); // where index is the variable you are looping over
async_call(...).then(callback);
This can be written more compactly by making createCallback
an anonymous function:
var callback = (function(curIndex){
return function(text) {
// use text and curIndex...
};
})(index);
async_call(...).then(callback);
For more information on closures and functions in JavaScript, see this comprehensive answer.
Upvotes: 1