Reputation: 1915
Can JavaScript's setTimeout
function be used with functions that are inside a closure? What if the call to setTimeout
is made from within that same closure?
With my attempts, it appears that you cannot. I'm not sure if I'm missing anything, though.
Basically, I would like to do this:
var ButtonCycler = (function() {
var ButtonCycler = {};
var autoCycle;
var idx = 0;
var buttonIds = [];
buttonIds[0] = "id1";
buttonIds[1] = "id2";
//"Public" methods
ButtonCycler.startAutoCycle = function() {
autoCycle = true;
cycleButtons();
}
ButtonCycler.stopAutoCycle = function() {
autoCycle = false;
}
//Worker function (effectively private because it's in the closure)
function cycleButtons() {
var radioButton;
if(autoCycle) {
radioButton = document.getElementById(buttonIds[idx]);
radioButton.checked = true;
idx++;
if(idx >= buttonIds.length) {
idx = 0; //Start over at first button
}
setTimeout('cycleButtons()',2500); //Delay for 2.5 seconds
}
}
return ButtonCycler;
})(); //IIFE
Then in onload
for the page, I can do this:
ButtonCycler.startAutoCycle();
And when the user manually clicks one of the radio buttons, I can do this:
ButtonCycler.stopAutoCycle();
And the mechanism for performing the cycling can be nicely encapsulated in the closure.
When I try this, I get an error that cycleButtons
does not exist. The initial call to cycleButtons
succeeds, though. It is the call initiated by the call to setTimeout
that is failing.
Upvotes: 0
Views: 66
Reputation: 5964
You are passing cycleButtons()
as a string which will later be called using eval
. This will assume that cycleButtons
is available at the global scope (which it is not). Instead, pass the reference to the actual function:
setTimeout(cycleButtons, 2500);
Upvotes: 5
Reputation: 2519
Your setTimeout is incorrect and you should probably use clearTimeout to simplify your code. Here's a example of how you can simplify it:
var ButtonCycler = (function () {
var ButtonCycler = {};
var autoCycle;
var idx = 0;
var buttonIds = [];
var timer;
buttonIds[0] = "id1";
buttonIds[1] = "id2";
//"Public" methods
ButtonCycler.startAutoCycle = function () {
cycleButtons();
}
ButtonCycler.stopAutoCycle = function () {
clearTimeout(timer);
}
//Worker function (effectively private because it's in the closure)
function cycleButtons() {
var radioButton;
radioButton = document.getElementById(buttonIds[idx]);
radioButton.checked = true;
idx = (idx < buttonIds.length - 1) ? idx + 1 : 0;
timer = setTimeout(function () {
cycleButtons();
}, 2500); //Delay for 2.5 seconds
}
return ButtonCycler;
})(); //IIFE
Upvotes: 0