user192632 user192632 - 7 months ago 15
Javascript Question

setInterval calling function with an undefined parameter

This question has been flagged as already answered with a link provided above. However, I already read that answer and it only answered how to use setInterval in a for loop. There were no functions being called with parameters passed to them in that solution, and that is my situation, so I couldn't use it to fix my situation.

I'm fairly new to programming, so I'll try to describe as best as I can. In setInterval, I am passing a parameter to the function toggleClusters which setInterval calls. The debugger shows the parameter as being correct. It is a reference to an array position that holds an object literal that contains map marker objects. I seem to be misunderstanding something about what values stay around and what do not when using setInterval, because the debugger shows the correct object literal being passed as an arg, but when the function is called, the debugger shows the obj that is supposed to be passed as undefined. Is it that this passed value no longer exists when the function is called?

function setClusterAnimations() {
for (var i = 0; i < clusters.length; i++) {
//intervalNames stores handle references for stopping any setInterval instances created
intervalNames.push(setInterval(function () {
//clusters[i] will hold an object literal containing marker objects
toggleClusters(clusters[i]);
}, 1000));
}
}
//cObj is coming back as undefined in debugger and bombing
function toggleClusters(cObj) {
var propCount = Object.keys(cObj).length;
for (var prop in cObj){
if (prop.getZIndex() < 200 || prop.getZIndex() == 200 + propCount) {
prop.setZIndex(200);
}
else {
prop.setZindex(prop.getZIndex() + 1)
}
}
}

Answer

This is typically the issue with such asynchronous calls as with setInterval(). You can solve this in different ways, one of which is using bind():

for (var i = 0; i < clusters.length; i++) {
    //intervalNames stores handle references for stopping any setInterval instances created
    intervalNames.push(setInterval(function (i) {
    //clusters[i] will hold an object literal containing marker objects    
        toggleClusters(clusters[i]);
    }.bind(null, i), 1000));
}

The toggleClusters(clusters[i]) statement will only be executed when your loop has finished, at which time i will be beyond the correct range (it will be clusters.length). With bind(), and mostly with the function parameter i, you create a separate variable in the scope of the call back function, which gets its value defined at the moment you execute bind(). That i is independent from the original i, and retains the value you have given it via bind().

Comments