0

I created a little script in Javascript, which is supposed to show to all the clients connected on the page some informations, actually an image every 90 seconds. This function is working perfectly fine on my computer, but as soon as I have to reload the page, all the process restart.

I don't know if there is a way to make the server calling this function, like this

//This should be a "server" variable in which users should be able to add their own image :
var images = [
  ['Canyon', 'https://www.w3schools.com/css/img_fjords.jpg'],
  ['Car Jumping', 'http://www.gettyimages.fr/gi-resources/images/Embed/new/embed2.jpg'],
  ['Birds Flying', 'http://ekladata.com/qWGncUdJ7U5k2vvmc1au-ZLnjlc.jpg'],
];

function Display (imagesarray) {
  var rnd = Math.floor((Math.random() * imagesarray.length - 1) + 1);
  document.getElementById("image").src = imagesarray[rnd][1];
}

function Timer(countDownDate) {
 
 var x = setInterval(function() {

  // Get todays date and time
  var now = new Date().getTime();
  // Find the distance between now an the count down date
  var distance = countDownDate - now + 2;
  // Time calculations for days, hours, minutes and seconds
  var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
  var seconds = Math.floor((distance % (1000 * 60)) / 1000);
  
  // Output the result in an element with id="demo"
  document.getElementById("countdown").innerHTML = ("0" + minutes).slice(-2) + ":" + ("0" + seconds).slice(-2);
  
  // If the count down is over, write some text 
  if (distance < 0) {
   clearInterval(x);
   document.getElementById("countdown").innerHTML = "FINISHED !";
   Display(images);
  }
 }, 1000);
}

//This will call the Timer() function to end it in 01:30, and launch it again 10 seconds after the end of the previous call.
var y = setInterval(Timer(new Date().getTime() + 10000), 500);
p {
  text-align : center;
  font-size : 48px;
  margin : 0px;
}

#note {
  text-align : center;
  font-size : 12px;
  margin : 0px;
}

#image {
  display : block;
  margin : auto;
  width : 150px;
  height : 150px;
}
<p id="note">Counting only 10 seconds for example</p>

<p id="countdown">00:10</p>

<img id="image" src="http://vignette4.wikia.nocookie.net/destinypedia/images/b/b9/Unknown_License.png/revision/latest?cb=20130810221651">

Does anyone know how this could be managed by the server, so everybody have the same timer and the same picture displayed at the same time ?

Thanks a lot for your help !

[EDIT 1] The backend language I am using is PHP on this project

Louis 'LYRO' Dupont
  • 1,052
  • 4
  • 15
  • 35

2 Answers2

0

You need to keep a persistent connection with the server possibly through websockets OR you can easily just send a variable from the server which tells the clients in how many seconds the next appearance should start.

itsundefined
  • 1,409
  • 2
  • 12
  • 32
0

Breaking news: Time passes the same way all around the world :-D.

So there is no real need of "persistent connection" or so, as long as the users have set-up the time correctly on their computer. You just need to use the same base date for every user. Timestamps are very good at this because there is no time-zone problem with them.

Also note that it might be a better idea not using setTimeout setInterval for measuring time, because setTimeout could be renamed as runAfterAtLeastThatTimeIfYouDontHaveBetterToDo(). In deed, putting a setIterval(()=>{},1000) does not guarantee it will run every 1s, and you might experience desynchronization if the user switch tabs while browsing. You'd better run the interval function more than every seconds -every 10ms for example- if you want it to be accurate.

Usualy, I use requestAnimationFrame for displaying timer.

code :

In this code, I use the same base date for every users (I didn't put any 10s chill-time because I am lazy, but you can see the idea) :

const startDate = 0; // Unix epoch
const interval = 90000; // 90 seconds

var now = Date.now();

var count = (now - startDate) / interval; // should have run {{count}} times since Unix epoch
var next = Math.ceil(count) * interval + startDate; // so the next time it should run is at timestamp {{next}}

function timer() => {
  var now = Date.now();
  distance = next - now;
  if (now >= next) {
    document.getElementById("image").src = "http://domain.tld/my-script.php?now=" + now; // the query string parameter is just to avoid browser caching the image
    next += interval;
  } else {
    var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60))
    var seconds = Math.floor((distance % (1000 * 60)) / 1000);
    document.getElementById("countdown").innerHTML = ("0" + minutes).slice(-2) + ":" + ("0" + seconds).slice(-2);
  }
}

var requestID = window.requestAnimationFame(timer);
// use window.cancelAnimationFrame(requestID) to cancel the timer

A note on the img.src part:

this is the only part where the server is mandatory, you must implement a script that will send the image based on time. I added a queryString ?now=timestamp to avoid browser caching the image, and not keeping it up to date, but the server should rely on it's own date/time to display the image, not the one sent by the user.

PS : Note that I don't have anything against persistent connection via websocket or so, but that sounds a bit overkill for just displaying a timer and an image on a regular basis. If you think all your user have set their computer's time correctly and that it's not a big deal if some are not synched, use this solution. Otherwise, go for websocket.

n00dl3
  • 21,213
  • 7
  • 66
  • 76
  • 1
    "Time passes the same way all around the world" — Fun fact, that isn't actually true: https://phys.org/news/2010-09-pair-aluminum-atomic-clocks-reveal.html – Quentin Apr 19 '17 at 09:40
  • @Quentin, I guess it's a matter of opinion, "everthing is relative" ! ;-D – n00dl3 Apr 19 '17 at 09:44