When I use a setTimeout() in a for() loop in a greasemonkey script, it doesn’t appear to work at all. However, the exact same code works fine if I run it in the Firebug console. Here’s the code:
// ==UserScript==
// @name setTimeout test
// @include *
// @run-at document-end
// ==/UserScript=
function test(delaytime) {
alert("test called with "+delaytime);
}
function test2() {
for( var i = 0; i < 100; i+= 10 ) {
setTimeout('test('+i+');', i);
}
}
setTimeout(test2,10);
If I replace the for() loop with explicit calls like the following, then it works fine.
setTimeout(function() { test( 0); }, 0);
setTimeout(function() { test(10); }, 10);
setTimeout(function() { test(20); }, 20);
setTimeout(function() { test(30); }, 30);
setTimeout(function() { test(40); }, 40);
setTimeout(function() { test(50); }, 50);
setTimeout(function() { test(60); }, 60);
setTimeout(function() { test(70); }, 70);
setTimeout(function() { test(80); }, 80);
setTimeout(function() { test(90); }, 90);
What’s the difference? Is there any way I can get the for loop generated setTimeouts to work in greasemonkey?
Because when the string is evaled at the time the setTimeout fires in order to execute the function, the loop has run it’s course and
iis sitting at the last value of the loop.To freeze the value of
ifor each call to setTimeout, you need to capture it in a function closure like this:This also has the advantage of getting rid of the eval in the setTimeout parameter.