Reputation: 11260
I have an issue with a function call in setTimeout in a loop.
The parameters passed to the function are the last values computed in the loop for each iteration, please see example below.
for(var i=0; i<datesYM.length; ++i) {
console.log(datesYM[i]);
var dateYM = datesYM[i];
setTimeout(function() {
myDB.markMonthsValuesAsUpdated2(myDoctorId, dateYM)
}, Math.floor(Math.random()*5001));
}
myDB.markMonthsValuesAsUpdated2 = function(myDoctorId, dateYM) {
console.log(dateYM);
[...]
Prints:
2012-01
2012-02
2012-03
2012-04
2012-05
2012-06
2012-072012-07
2012-07
2012-07
2012-07
2012-07
2012-07
2012-07
Upvotes: 2
Views: 296
Reputation:
Create variable scope via a function that creates and returns the timeout handler.
function create_timeout_handler(myDoctorId, dateYM) {
return function() {
myDB.markMonthsValuesAsUpdated2(myDoctorId, dateYM)
};
}
Then invoke that function and pass it whatever needs to be scoped.
setTimeout( create_timeout_handler(myDoctorId, dateYM), Math.floor(Math.random()*5001));
This is because every function you were giving to setTimeout
was being created in the same variable scope, so they were all referencing the same dateYM
variable, which was being overwritten in the loop.
Passing dateYM
to another function that creates and returns the handler ensure that each handler is referencing the dateYM
variable that was unique to each invocation of create_timeout_handler
.
Upvotes: 1
Reputation: 60414
Wrap the body in its own self-executing function to force a new scope:
for(var i=0; i<datesYM.length; ++i) {
console.log(datesYM[i]);
var dateYM = datesYM[i];
(function(dateYM) {
setTimeout(function() {
myDB.markMonthsValuesAsUpdated2(myDoctorId, dateYM)
}, Math.floor(Math.random()*5001));
})(dateYM);
}
Without this, every function created in the loop closes over the same instance of dateYM
, which has the value of the last iteration by the time any of those functions execute. Since JavaScript has function scope, the wrapper function creates a new dateYM
on each iteration, so that each new function passed to setTimeout
has its own instance.
Upvotes: 5