jQuery countdown: serverSync still lags for 1-2 seconds by clients - php

I'm building auction site and I'm using jQuery countdown from Keith Wood to show ending time of auctions. I need to have synchronized countdown time with server for all my clients. So far I have implemented jQuery countdown with serverSync function. It works fine, but when few seconds pass, countdown lags by 1 or 2 seconds.
How can I perfectly synchronize time for all clients, if even possible?
UPDATE: I'm also polling (500ms interval) php file, which updates all auctions (real-time effect) and in this code I also echo out new "polled" countdown from database (because when user bids in last 10 seconds of auction, countdown goes up + 10 seconds). So I think here is the problem, cause on the client side, not every poll starts in the same time, it depends when client refreshes page and so one and it affects countdown. Basically every 500ms I call in my poll.php this (which updates the countdown from database):
var syncDate = new Date("'.$formatEndDate.'");
jq("#defaultCountdown-'.$bidded_id.'").countdown("option", {until: syncDate, serverSync: serverTime});
My code so far, which lags for 1 or 2 seconds:
$(function () {
var d = new Date("'.$endingDate.'");
$('#defaultCountdown').countdown({until: d, onExpiry: endAuction,
expiryText: '<div class="bid-over">Ended</div>', format: 'HMS',
onTick: watchCountdown, serverSync: serverTime });
});
function serverTime() {
var time = null;
var url = "serverTime.php";
jq.ajax({
url: url,
async: false,
dataType: "text",
success: function (text) {
time = new Date(text);
},
error: function (http, message, exc) {
time = new Date();
}
});
return time;
}
and serverTime.php:
<?php
//This is how I get server time
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Fri, 1 Jan 2010 00:00:00 GMT"); // Date in the past
header("Content-Type: text/plain; charset=utf-8"); // MIME type
date_default_timezone_set('Europe/Ljubljana');
$srvDate = getdate();
$d = $srvDate['mday'];
$m = $srvDate['mon'];
$y = $srvDate['year'];
$h = $srvDate['hours'];
$i = $srvDate['minutes'];
$s = $srvDate['seconds'];
$nowDate=date("$y-$m-$d $h:$i:$s");
$nowDate=str_replace("-","/",$nowDate);
echo $nowDate;
?>

Related

PHP: Execute a function inside a while loop every 10 seconds

I've this while loop here:
$payment_timeout = time() + 300;
while ( time() < $payment_timeout ) {
if (is_valid()) {
continue;
}
break;
}
This loop get's called via an AJAX function. The plan is to wait until a customer paid something. To check this, I've build a is_valid() function which does a check against the database to check if the order was paid.
The problem is that in this case my database will crash because of the amount of requests. So I'm looking for a way to execute the check every 10 seconds or so and the other times just do the continue.
Is there a way to do this?
You can do a "long-polling" with javascript.
It is very simple: a javascript function that runs every X seconds (in your case 10) and do a call to the server.
From this post Using setInterval() to do simplistic continuous polling you can do:
// This function is called every 10000 milliseconds (10 seconds)
function refresh() {
// make Ajax call here, inside the callback call:
// call itself again after 10 seconds
setTimeout(refresh, 10000);
}
// if you want to wait 10 seconds for the first call
setTimeout(refresh, 10000);
// or if you want to call immediately the first time
refresh();
If you want to stop the calls after 5 minutes, you just have to set a counter variable and check it in the refresh function.
Something like (pseuso code):
IF YOUR_COUNTER < 5 MINUTES THEN
CALL REFRESH AGAIN
at the end of the refresh function.
Below is a simple generic implementation of a polling mechanism in Javascript, working with variable endpoint, intervals, durations, and callback.
The assumption is that you remove the while loop from the PHP code, and make sure you send back a valid JSON response. In the callback parameter I've given below the assumption is that PHP sends back json_encode(['paid' => true]).
// interval & duration in seconds
function poll(endpoint, interval, duration, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', endpoint);
xhr.onload = function() {
var message;
try {
message = JSON.parse(xhr.response);
} catch(err) {
// malformed json
}
if (duration >= 0 && callback(message) !== false) {
setTimeout(function() {
poll(interval, duration - interval, callback);
}, interval * 1000);
}
};
xhr.send();
}
// usage
var endpoint = '/your-validity-check.php',
interval = 10, // every 10 seconds
duration = 5 * 60, // for 5 minutes
callback = function(response) {
var date = new Date();
console.log(response.paid);
// return false to abort the polling when we know the purchase is paid
if (response.paid) {
window.alert('Thank you for your purchase!');
return false;
}
};
poll(endpoint, interval, duration, callback);
NB: XHR = XMLHttpRequest; what #Giacomo shows is not long-polling, long-polling is a client-server technique which involves keeping connection requests open.
I'm using now a setInterval() function to check:
let interval = setInterval( function () {
//If max time of 5 minutes exceeded (5 * 60000) I leave the interval
if ( new Date().getTime() - startTime > 300000 ) {
clearInterval( interval );
}
//Here I'm doing my AJAX request to check the payment status
}, 5000 ); //<- Execute every 5 seconds
This works great for me and is simple

jQuery countdown with update

We are using the following countdown function on our bidding site.
setInterval(function(){
$(".countdown").each(function(){
var seconds = $(this).data('seconds');
if(seconds > 0) {
second = seconds - 1;
$(this).data('seconds', second)
var date = new Date(null);
date.setSeconds(second);
$(this).html(date.toISOString().substr(11, 8))
}
else
{
$(this).html("Finished");
alert('finished');
}
});
}, 1000);
we pass the number of seconds where we want the counter to appear (sometimes more than once on our page:
echo "<div id=\"".$auctionid."\" class=\"countdown\" data-seconds=\"".$diff."\"></div>";
So far it should be clear an it works. Now we have a situation where when someone bids somewhere on the site - the time left for auction is prolonged for 15 seconds, which is written to mysql.
$diff variable is calculated from mysql end time, and it's passed to jQuery on page load.
The question is how to check the mysql time for that auction and sync it in jQuery counter? We had the idea to maybe check every 5 seconds and after it reaches zero to make sure it's over? Any suggestions?
It should look nice to the user.
EDIT:
This is what we have so far:
$(".countdown").each(function() {
var countdown = $(this);
var auctionid = $(this).attr('id');
var interval = setInterval(function() {
var seconds = countdown.data("seconds");
if( seconds > 0 ) {
var second = --seconds;
var date = new Date(null);
date.setSeconds(second);
countdown.data("seconds", second).html(date.toISOString().substr(11, 8))
} else {
// countdown.html("Finished <img src=\"loading.gif\" class=\"tempload\">");
startUpdateingTimeFromDatabase(auctionid);
countdown.html("Finished");
clearInterval(interval);
}
}, 1000);
});
function startUpdateingTimeFromDatabase(auctionid) {
$.getJSON("timer.php?auctionid="+auctionid, function(response) {
// console.log(response.seconds);
$(".countdown#"+auctionid).data("seconds", response.seconds);
if( response.seconds > 0 ) {
// setTimeout(startUpdateingTimeFromDatabase(auctionid), 1000);
} else {
}
});
}
This simply isn't doing what we need it to do. We need to update the seconds (query startUpdateingTimeFromDatabase) every time it reaches zero. Now I think there are two approaches. First is simply return seconds via startUpdateingTimeFromDatabase function and then do everything in the main function, second is update the div via startUpdateingTimeFromDatabase. I think first will be better but I simply can't find a way to do it properly.
Any help is appreciated. Thanks.
You store the seconds left in the elements data. So why not fetch the remaining time maybe via ajax and just pass the new seconds to the elements? Within the next interval run all times will be updated.
Something like this:
$.get("yourGetRemainingTimeScript.php", {auctionId: 1}, function(response) {
$(".countdown").data("seconds", response.seconds);
});
How you check and get the remaining time is up to you. You can set the time for all everywhere again.
$(".countdown").data("seconds", 1337);
Another hint from my side: don't loop all elements with each in the setInterval. Create the intervals inside the loop once. Then your script doesn't need to search every second again over and over for the elements.
And clear the interval when it's finished.
$(".countdown").each(function() {
var countdown = $(this);
var interval = setInterval(function() {
// do your stuff ...
// when finished stop the interval
if( finished ) {
clearInterval(interval);
}
}, 1000);
});
Full working example.

Check time changing automatic

There is a streaming channel which displays for 24 hours per day and I want to display that for certain hours of day in my website. I use a code as bellow:
$now = date('G',time());
$start = 13;
$end = 14;
if($now >= $start && $now <= $end){
echo "streaming video";
}
else{
echo "image";
}
It works when I do refresh/load page. But I want this program to check the time and do reactions without it is needed to do reload the page. So, when the time comes up to 14:00 the video will not being displayed anymore but the image instead of video and when the time comes to 13:00 to display video instead of image. Can be done with php or it is needed ajax or something else?
Waiting for some help.
Create a javascript function that performs an ajax call to a time function which can decide to set the stream or an image:
<div id="stream-content"></div>
setInterval(function() {
$.ajax({
url : "/gettime.php",
type: 'GET',
success: function(data){
//check time, if correct, set video to the div #stream-content otherwise, set an image as the content
}
});
}, 1000);

Is my code a performance killer?

I am showing the value of the timer.php through AJAX in index.php . However I am concern about the performance of this, if it is a server killer if there are 30 people online, and things like this. Do you suggest me some edits?
Thank you.
index.php
<script language='JavaScript'>
setInterval( 'SANAjax();', 1000 );
$(function() {
SANAjax = function(){
$('#dataDisplay').load('timer.php');
}
});
</script>
<div id="dataDisplay"></div>
timer.php
function time_difference($endtime){
$days= (date("j",$endtime)-1);
$hours =date("G",$endtime);
$mins =date("i",$endtime);
$secs =date("s",$endtime);
$diff="'day': ".$days.",'hour': ".$hours.",'min': ".$mins.",'sec': ".$secs;
return $diff;
}
$future_time = mktime(0, 0, 0, 9, 19, 2011);
$now_time = strtotime("+2 hours");
$end_time = $future_time - $now_time;
$difference = time_difference($end_time);
if ($future_time <= $now_time ) { echo "Date reached"; } else { echo $difference; };
?>
Depends on your server specs and number of clients, this could quickly become a server-killer.
The multiple calls to a file every second will quickly put a lot of load for nothing though, so best practice calls for using a javascript timer countdown. I particularly like this one: http://stuntsnippets.com/javascript-countdown/
And for the jQuery implementation:
<script type="text/javascript">
var myDate = new Date(); //Retrieve actual date
myDate.setTime(this.getTime() + (3600 * 2)); //Add two hours
$(document).ready(function() {
$("#time").countdown({
date: myDate.toGMTString(),
onComplete: function( event ){
$(this).html("completed");
},
leadingZero: true
});
});
</script>
<p id="time" class="time"></p>
This should be enough, no more need for PHP calls and the client does everything.
By setting a setInterval for every second, you are basically saying that for 30 clients, you will be getting roughly 30 txn per second to your php server. Its hard to say its a performance killer outside of just saying you will have to handle 30tps for this simple call. I would first quesiton why you are doing this with a server side script. You could just as easily give the html file a datetime when the page loads and do the countdown with just javascript in the browser.
I use jQuery Countdown http://keith-wood.name/countdown.html to put a timer on my pages to let the user know when they are going to be logged out of the system due to inactivity.
You can bind a function to the counter expiring event.
http://code.google.com/p/jquery-countdown/ ...Simple example
http://keith-wood.name/countdown.html ...shows off all the bells and whistles...
It can be as simple as the first one or as detailed as the second!
-=Bryan

Jquery Countdown Server sync issue

I'm trying to create a countdown for an event. I'm using Jquery Countdown
I have this code:
$(function () {
var fecha = new Date("July 30, 2011 00:00:00");
$('#defaultCountdown').countdown({
until: fecha,
format: 'DHMS',
expiryUrl: "http://www.google.com",
serverSync: serverTime,
timezone: -4
});
});
function serverTime() {
var time = null;
$.ajax({
url: 'serverTime.php',
async: false,
dataType: 'text',
success: function (text) {
time = new Date(text);
},
error: function (http, message, exc) {
time = new Date();
}
});
return time;
}
The script is working fine, but when I try to change the clock date, the countdown changes.
Any idea why?
I imagine you created the serverTime.php file on your server?
http://keith-wood.name/countdown.html
Tab Timezones has the PHP code you'll need to add to serverTime.php for your script to use that. Also may want to fully qualify that to something like url: 'http:yourdomain.com/serverTime.php' But using that it should use your server time not your local PC time. If your server is on your local PC, then well... it would change.
I went to their site, with their example, and changing my system time affects their countdown as well. Their code relies on local system times.
What I see when you get the server time form the ajax call, it is not creating the JavaScript date object.
I searched and below worked for me.
// Split timestamp into [ Y, M, D, h, m, s ]
var t = "2010-06-09 13:12:01".split(/[- :]/);
// Apply each element to the Date function
var d = new Date(t[0], t[1]-1, t[2], t[3], t[4], t[5]);
alert(d);
// -> Wed Jun 09 2010 13:12:01 GMT+0100 (GMT Daylight Time)

Categories