2

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-07

2012-07
2012-07
2012-07
2012-07
2012-07
2012-07
2012-07

2 Answers 2

5

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.