I have some code like this:
for(var id=0; id < message.receiver.length; id++){
var tmp_id = id;
zlib.gzip(JSON.stringify(message.json), function(err, buffer){
...
pushStatusPool[message.receiver[tmp_id]] = null; // fix memory leak
delete pushStatusPool[message.receiver[tmp_id]];
...
});
}
And I got a warning that using tmp_id in closure may cause problem because it is a mutable variable.
How could I avoid that? I mean how could I send an immutable variable to callback since this is a for loop and I can not change code of zlib.gzip? Or in other words, how could I pass a argument to a closure?
You need to create a scope to correctly capture tmp_id using a self-executing function. That's because the entire for loop is one scope, meaning each time through, you're capturing the same variable. So the callback will end up with the wrong ids, because temp_id's value will get changed before the callback is called.
I'd ignore (or shut off) the warning, though, which seems to be complaining that because temp_id is mutable, you might reassign it. That's sort of silly. If you really want to fix it, try using the const keyword instead of var.
for(var id=0; id < message.receiver.length; id++){
(function(){
const tmp_id = id;
zlib.gzip(JSON.stringify(message.json), function(err, buffer){
...
pushStatusPool[message.receiver[tmp_id]] = null; // fix memory leak
delete pushStatusPool[message.receiver[tmp_id]];
...
});
})();
}
I have faced the same problem and solved it slightly modifying the answer of user24359, by passing the id to the closure:
for(var id=0; id < message.receiver.length; id++){
(function(tmp_id){
zlib.gzip(JSON.stringify(message.json), function(err, buffer){
...
pushStatusPool[message.receiver[tmp_id]] = null; // fix memory leak
delete pushStatusPool[message.receiver[tmp_id]];
...
});
})(id);
}
here a simplification of user24359's great answer. This is the solution:
var object = {a:1,b:2};
for (var y in object){
(function(){const yyy = y;
setTimeout(function(){console.log(yyy)},3000);})();
}
The above code logs a b and is the solution. The following code logs b b :
var object = {a:1,b:2};
for (var y in object){
setTimeout(function(){console.log(y)},3000);
}
I've faced the same problem in protractor. Solved it using following code -
(function(no_of_agents){
ptor.element.all(by.repeater('agent in agents').column('displayName')).then(function(firstColumn){
console.log(i, '>>>>>Verifying the agent Name');
var agentsSorted = sortAgentsByName();
//verify the agent name
expect(firstColumn[no_of_agents].getText()).toEqual(agentsSorted[no_of_agents].name);
//now click on the agent name link
firstColumn[no_of_agents].click();
ptor.sleep(5000);
});
})(no_of_agents);