0

I need a very fast timer in Javascript. The timer resolution is considered to be 10 milliseconds. I already implemented a working timer, but the problem is, that the time is always depending on how many other ressources are running in the Browser. And when an animated GIF is running, my timer won't work at all. This is the code (working!):

var timer = new Timer();

function Timer(){
    var time = 0;
    //Every 10ms we are incrementing the timer:
    setInterval(function(){
        time=time+1;
    },10);
    this.getTime=function(){return time;}
}

function testTimer(){
    var counter = 0;
    var resultsum = 0;
    var everytensum = 0;
    setInterval(function(){
        counter = counter + 1;
        window.timeoutTesterRunning = true;
        var timeoutTester = new TimeoutTester();
        setTimeout(function(){
            console.log(counter+": "+timeoutTester.getResult());
            resultsum = resultsum+timeoutTester.getResult();
            console.log(resultsum);
            if(counter%10==0){
                console.log("Counting last 10 seconds: "+(resultsum-everytensum));
                console.log("Counting last "+counter+" seconds: "+resultsum);
                everytensum = resultsum;
            }
        },1200)
    }, 3000);
}

function TimeoutTester(){
    var result;
    var snap_time1 = timer.getTime();
    setTimeout(function(){
        var snap_time2 = timer.getTime();
        result = snap_time2-snap_time1;
    },1000);
    this.getResult=function(){return result;}
}

Now the results from the console.log (the sums are in brackets):

[10:10:54.466] 1: 100 (100)
[10:10:57.466] 2: 100 (200)
[10:11:00.466] 3: 100 (300)
[10:11:03.466] 4: 100 (400)
[10:11:06.466] 5: 100 (500)
[10:11:09.465] 6: 100 (600)
[10:11:12.466] 7: 101 (701)
[10:11:15.467] 8: 100 (801)
[10:11:18.467] 9: 100 (901)
[10:11:21.467] 10: 100 (1001)
[10:11:21.476] Counting last 10 seconds: 1001
[10:11:24.467] 11: 100 (1101)
[10:11:27.468] 12: 100 (1201)
[10:11:30.467] 13: 100 (1301)
[10:11:33.478] 14: 60 (1361)  //Animated Gif started: Less countings! ("Time runs longer")
[10:11:36.476] 15: 57 (1418)
[10:11:39.482] 16: 58 (1476)
[10:11:42.472] 17: 61 (1537)
[10:11:45.474] 18: 56 (1593)
[10:11:48.484] 19: 48 (1641)
[10:11:51.470] 20: 55 (1696)
[10:11:51.476] Counting last 10 seconds: 695
[10:11:51.482] Counting last 20 seconds: 1696

The counter runs quite regular. But when the Browser is busy (by a animated GIF), Javascript has no time to set the intervals correctly. The function Timer() just doesn't receive the time it needs to increment var time, so the values are far to low (when I first started testing, the values were even lower at ~40, but I was able to rise them to ~55 by using functional implementation).

Anybody knows how we could get that Javascript timer working? Or is it just impossible to prevent the browser killing the timer?

9
  • What is the purpose of the timer? You might be better off diffing two Date() objects, or using requestAnimationFrame. Commented Feb 20, 2013 at 14:29
  • 1
    Related: stackoverflow.com/questions/196027/… Commented Feb 20, 2013 at 14:33
  • @Quentin: The purpose is to create some exact animation with a resolution of 10 milliseconds. I know that the graphics resolution is often only 15 milliseconds (except chrome has about 4ms), but I'll probably use about 20ms for the shortest event, so that shouldn't be any problem. The problem is that my browser doesn't allow the timer to run smoothly under certain circumstances. Commented Feb 20, 2013 at 14:34
  • @epascarello: It actually has nothing to do with setTimeout(). The running function of the timer is a setInterval(), I'm going to change the tagging of the question... Commented Feb 20, 2013 at 14:36
  • @Marcus — Really sounds like the usecase for requestAnimationFrame Commented Feb 20, 2013 at 14:37

3 Answers 3

3

setInterval was never made to do timing, but to schedule execution! It's intervals are not reliable. If you want to do timing, use Date timestamps:

function Timer(){
    var start = Date.now();
    this.getTime=function() {
        return Date.now() - start;
    }
}

That way, you get 1 millisecond resolution.

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

7 Comments

The problem is that to implement a timer, you need to have a "driving" function, it can be a setInterval or a setTimeout-recursive function. And it doesn't matter if I use Date.now(), with all solutions I still have the same problem while running an animated Gif. It looks like Javascript animation is never really reliable due to bad implementation in the browser. That's very sad, but sometimes it's good to know what is possible and what not...
So what do you want to drive your timer? And for what would you need a "reliable" interval for animation, if the browser is already too busy to do it?
I just thought that it's possible to do fast animations in the browser, with exact timing. But it turned out that this can't be done in Javascript. So now I need immediately call the Forefox developers to reverse their ugly Gif bugs implemented in newer Firefox. This is gonna be a mess. :(
Fast does not necessarily need to be Exact (a kind of macroscopical uncertainty). You can do very fast animations in JS, yet you will need to let the browser do the timing for you.
The uncertainity is exactly my problem. Sure, I found out now how to get 250 fps, but soon when the animated Gif starts, I'm getting something like 70 or 80 fps. That's because the method Date.now() has a huge uncertainity. I'm looking for a more mathematical solution now, to get at least 70fps... (EDIT: with "fps" I mean timer events, no real frames)
|
0

var timer = function(f, args) { t = Date.now(); f.call(args); console.log(Date.now() - t)}

Comments

0

Because the implementation of a timer wasn't possible, I ended up with a hole different solution, it's a kind of brut-force-running the animation within a setInterval:

function animate(elementId,pictureTimeArrayName){
    var elementStyle = document.getElementById(elementId).style;
    var pictureTimeArray = window[pictureTimeArrayName];

    function toInterval(startDate, timeSinceStart, picture){
        var interval = setInterval(function(){
            if(Date.now()-startDate>=timeSinceStart){
                clearInterval(interval);
                elementStyle.background = "url("+picture+")";
            }
        },2);
    }

    setInterval(function(){
        var startDate = Date.now();
        for(var i=0;i<pictureTimeArray.length;i++){
            toInterval(startDate,pictureTimeArray[i].time,pictureTimeArray[i].picture);
        }
    },pictureTimeArray[pictureTimeArray.length-1].time);
}

While an array looks like this:

var array_1 = [{picture: "animations/pic_1.gif", time: "30"},
               {picture: "animations/pic_2.gif", time: "60"},
               ...
               {picture: "animations/pic_36.gif", time: "1080"},];

This looks quite good (for >=30 fps). But: When an animated Gif is running, it's still not that smooth anymore. And if it is an animation repeating itself, the drawings aren't always clean. In some never browser versions (from Firefox) the drawing is even worse than in older versions, and other browsers (Chrome) have their problems, too. Especially if you change the browser window in Chrome and get back to the window: The animation will look really weird.

So you probably better use Flash or another non-Javascript-solution for your professional animations.

4 Comments

…or you don't try to use animated GIFs, but do it with JS. With requestAnimationFrame you can get consistent high-FPS smooth animations, there is absolutely no need for Flash or Java these days.
You should know that there are animations and animations. Animations from beginners have all the same frame rate per picture. That's nice (you can easily use requestAnimationFrame for this), but unsuitable for professional animations. For professional animations, you must choose a high framerate (about 33 fps is good) and then you need to dynamicly adapt the time for every picture (some last for 15 or 20ms, others for 40ms). That's how real animation is done. But you're certainly right about Java, applets are dead for a long time. And who's using JavaFX since more user have Flash installed? ;)
However, if you really want to make a modern website with maximised animation for the newest browsers, you won't use requestAnimationFrame, but you'll use WebGL: en.wikipedia.org/wiki/WebGL
Even WebGL animations do use requestAnimationFrame for tick loops.

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.