7

I have two JavaScript countdown timers (for a game), and a MySQL table to receive data from AJAX calls from either one.

The process is the following:

  1. a client starts the timer, writes it's data1 MySQL column so that it started the timer, and a time1 column with the current timestamp (with .01s precision, from the PHP call as MySQL doesn't do that)

  2. the other client (polling the server at 2s intervals) detects the change, and starts a timer, but immediately subtracts (it's a countdown timer) ctime - time1 where ctime is the timestamp from the second clients call (also given by the PHP) and time1 is the timestamp what the first client wrote when it started the timer.

This method is supposed to eliminate the delay caused by the 2s intervals of the polling, but regardless of if it does or not (I'm not really sure to be honest), the sync between the timers varies. Sometimes they are dead exact, sometimes they are off by up to as much as 3 seconds. (It's unreliable.)

Here's some of my relevant code I'm using:

var timerRunning, timeRemaining, responseTime;

function restartLocalTimer() {
    var d = new Date();
    responseTime = d.getTime()/1000;
    timerRunning = true;
    timerTick();
}

function restartSyncTimer(resp) { // resp is the AJAX response passed
    var d = new Date();
    responseTime = d.getTime()/1000 - parseFloat(resp["ctime"]) + parseFloat(resp["time"]);
    timerRunning = true;
    timerTick();
}

function timerTick() {
    d = new Date();
    timeRemaining = 20 - d.getTime()/1000 + responseTime;
    if (timerRunning) setTimeout("timerTick()",25);
}

All time values are in seconds. (Because of the database, might change to ms later.)

My questions are: Are there any additional (significant) delays I'm not accounting for? Is there a better way of doing this?

Also note: I'm open for jQuery (using it already for the AJAX calls), but don't want to use websockets.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Gabor Magyar
  • 926
  • 2
  • 9
  • 20
  • 1
    Ok, so I did read it this time. First of all: why use `setTimeout("timerTick()", 25)`? Why not `setTimeout(timerTick, 25)`. The first argument of `setTimeout` takes a function handle. Secondly: what if you use for example Google Chrome's Timeline or Network page in the console, does that help you identify what is causing the delay, or have you already tried that? – Martijn de Milliano Mar 05 '13 at 22:41
  • okay, the first thing is pretty much just aesthetics, but thanks anyway. as for the timeline, I'm going to look more into that. – Gabor Magyar Mar 06 '13 at 05:13
  • `resp["time"]` is the timestamp you are counting down to? – Bergi Mar 06 '13 at 10:27
  • it's the time I'm counting down from – Gabor Magyar Mar 06 '13 at 16:42

2 Answers2

1

I would take the same approach that desktop network multiplayer games take. Even during brief moments of connection disruption (e.g. "lag"), the client projects the expected trajectories during that time. In this case, you rely on a local interval, and update with the exact server time when you get the async heartbeat response.

landons
  • 9,502
  • 3
  • 33
  • 46
-1

setTimeout and its brothers are known to be unreliable. There is another post on this: Is there a more accurate way to create a Javascript timer than setTimeout? that gives some pointers.

Community
  • 1
  • 1
Martijn de Milliano
  • 3,908
  • 3
  • 36
  • 45
  • notice that setTimeout only executes the function periodically, but does not do any time releated calculations. that is done via Date – Gabor Magyar Mar 05 '13 at 21:32
  • 2
    It's because I don't think you've read my code, only saw the setTimeout() and immediately made assumptions. That is not how you post an answer. A comment, maybe. – Gabor Magyar Mar 05 '13 at 22:06
  • You're right, responded too fast. Bit me last week so I concluded too quickly this was the same. – Martijn de Milliano Mar 05 '13 at 22:37