View Full Version : setTimeout & setInterval issues

01-01-2007, 01:52 AM
I seem to be having some weird problems with setTimeout and setInterval. It is most notable in firefox(http://www.webtech101.com/uploads/dd/timeout.html), but with a little more work(lots of DOM manipulation on images) it occurs in other browsers. It looks like the timeout does not occur on the correct time, then it doubles up and executes the code twice. Does anyone know a way a around this?

01-01-2007, 02:16 AM
This sounds really familar. I had a similar issue in Firefox, and posted about it here: http://www.codingforums.com/showthread.php?t=72943 I thought they had resolved it already after my filing a bugzilla report.

01-01-2007, 11:25 AM
Most likely this has to do with the fact that a browser page isn't multi-threaded. What this means (as I understand it) is that - say, you have a timeout waiting to happen and you go ahead and set another one, the execution and/or the initiation of the second one may be held up until the first one is finished. Until browsers are made differently this will always be a potential problem. Best to not to rely upon more than one timeout or interval at a time.

01-01-2007, 06:55 PM
Yes, I think the problem is the single-threaded design structure. Now that I know what the problem is I think I have a solution. I was messing around with this, and came up with some code.

function TimeHelpers(){
this.timeouts = new Array();
this.intervals = new Array();
var this_ob = this;
this.caller = setInterval(function(){this_ob.call_interval()},1);
TimeHelpers.prototype.call_interval = function(){
for(var i = 0;i<this.timeouts.length;i++){
if(this.timeouts[i]['current'] == this.timeouts[i]['time']){
for(var i = 0;i<this.intervals.length;i++){
if(this.intervals[i]['current'] == this.intervals[i]['time']){
this.intervals[i]['current'] = 0;
TimeHelpers.prototype.timeout = function(code,time){
var l = this.timeouts.length;
this.timeouts[l] = new Array();
if(typeof(code) == 'function'){
this.timeouts[l]['code'] = code;
this.timeouts[l]['code'] = new Function(code);
this.timeouts[l]['current'] = 0;
this.timeouts[l]['time'] = time;
TimeHelpers.prototype.interval = function(code,time){
var l = this.intervals.length;
this.intervals[l] = new Array();
if(typeof(code) == 'function'){
this.intervals[l]['code'] = code;
this.intervals[l]['code'] = new Function(code);
this.intervals[l]['current'] = 0;
this.intervals[l]['time'] = time;

Basically, it is a wrapper around setInterval to allow multiple calls while only using one. It works, but is way to slow(it is consistent though). Anyone have any improvements that could make it faster? This is a really annoying problem.

01-01-2007, 07:17 PM
Rather than
this.timeouts[l]['code'] = function(){eval(code)};it would be more efficient to do:
this.timeouts[l]['code'] = new Function(code);

01-01-2007, 09:57 PM
Thanks Twey! Could you explain how that is better? I did a little research, and Function() constructor was described as being like eval().

01-02-2007, 01:09 AM
var v = new Function("alert(5);");is exactly the same as
var v = function() { alert(5); };It just evaluates the function once rather than multiple times (in your code, the code is evaluated again every time the function is called).

Actually, this won't be exactly equivalent anyway, since the scope of the string code when called by set(Timeout|Interval) is window, while the scope there (by either method) will be the function in which it's evaluated. You could instead do:
this.timeouts[l].code = Function.call(window, code);

01-02-2007, 01:23 AM
Also, note case: function != Function.

01-02-2007, 02:25 AM
function != Function

Isn't that only because the "new" is in front of the "Function" with a capital F?
For example, you can't say "new array[]". It has to be capitalized.

01-02-2007, 11:57 AM
One can't say "new Array[]" either ;)

ECMAScript is case-sensitive: function is a keyword, while Function is a constructor function.