trying to get difference in time handled for a game, but I haven't been able to get the math right (My weak point). Heres what I have so far:
function(timeSentToServer, serverTime) {
var difference = serverTime-timeSentToServer
var roundTripTime = Date.now()-timeSentToServer;
var responseTime = roundTripTime-difference;
timeDifference = responseTime;
}
timeSentToServer is the Date.now() when the request was sent. This is required due to multiple requests, and this function isn't within the scope of the function that sends the request.
serverTime is the time when the server received the request
the timeDifference should be a value that I can add to Date.now() to match it up with the current serverTime (probably a few milliseconds off, but thats acceptable)
however, I am running into an issue where one device Im testing against is just one second ahead of the server, and its throwing the whole calculation out of whack
e.g.: currentTime: 968952 sentTime: 968834 serverTime: 967742 difference: 1210
which results in being even more ahead of the server.
will Date.now()-difference be the solution I'm looking for? and also, is there any other articles I can read on the subject, and any different solutions?
Related
I created a real-time clock that updates every second. When I run it locally I see no errors. However when I uploaded it to my web host I saw a lot of error messages in the console every time the AJAX code runs.
I think that's the reason why web host suspended my site, telling that my site has performed too many requests.
Here is my code:
$(document).ready(function() {
setInterval(function() {
$('#time').load('timewithdate.php')
}, 1000);
setInterval(function(){
$('#time2').load('time.php')
}, 1000);
})
I'm not sure what kind of answer you are looking for. Your code is a certain way to kill a server: it's making 2 calls to the server every second for each client (read more about DDOS). There is no need to make a server call, just use javascript to get the current time and format it the way you want. You can have something like this:
$(document).ready(function() {
setInterval(function() {
let curTime = new Date();
let date = curTime.toLocaleDateString();
let time = curTime.toLocaleTimeString();
$('#time').text(date + " " + time);
$('#time2').text(time);
}, 1000);
})
The error is because you have effectively DDOS'd your own server with 2 requests every second * number of concurrent clients. I would strongly suggest you remove these AJAX requests and perform the countdown on the client side.
If you're trying to keep the clocks in sync with server time, get the time from the server when the page loads, then add seconds to it on the client side. Do not use AJAX for this, and do not use AJAX polling in future. It's an anti-pattern.
I have an app that requires countdown timer. Due date comes from my back-end with rest api. I need to coundown remaining time in my react native app. But I can't use smart phone's time. Because user can be in different timezone / country etc. How i can use server's due date response for react native?
Should I send also remaining time in seconds to user? So I can countdown that remaining time every second?
https://www.example.com/getDueDate [POST]
returns:
Y-m-d H:i:s (future) time like 2021-05-20 23:40:40
If I use classic countdown approach for javascript, I need to use smart phone's time. But I don't want to use that.
NTP server approach can be tricky for react-native side. It just simple counter.
Why not send both the server's current time and the due date? Then start your timer from there?
That being said, the time will still be off by the roundtrip time between your user and the server (which will depend on their internet connection and your server's response time).
Yes, it is possible to get time. I'm also using rest api (token base authentication and expiry token after certain time). I'm checking as given below
var l_currentDateTimeSeconds;
l_currentDateTimeSeconds=((new Date().getTime() - "your_time_from_api") / 1000);
if (parseInt(l_CurrentDateTimeSeconds) < parseInt(your_time_from_api))
{
//failure case ;
}
else
{
//Success case;
}
output of time (in variable) will be in seconds. Visit given below link, it may be help
https://aboutreact.com/react-native-get-current-date-time/
This is the technique i use and it's really effective.
Step 1.
Send due date from server (5pm)
Send current time from server (4pm)
Step 2.
Check clients current time (3pm)
Subtract currentTime(server) - currentTime(client) and call it timeOffset
Step 3.
setInterval to run every second using the code example below.
//import useState, useEffect from react-native
const [timer,setTimer]=useState();
var serverExpiryDate="'the time the event will expire gotten from server";
var currentTimeAtServer="the time you got from server via api";
var currentTimeAtDevice=new Date().getTime();
const timeOffset= currentTimeAtServer - currentTimeAtDevice;
//timeOffset is the time difference between the user's clock and the server clock. Calculated when user received response from server.
useEffect(() => {
let interval = setInterval(() => {
setTimer(() => {
let endT = new Date(serverExpiryDate).getTime(); //time from server;
let nowT = new Date().getTime(); //current time on user've device
nowT = nowT + timeOffset; //VERY IMPORTANT, helps to sync user's time with server.
let remaining = endT >= nowT ? Math.floor((endT - nowT) / 1000) : 0;
let stopCheck = remaining === 0 ? clearInterval(interval) : null;
return remaining;
});
}, 1000); //each count lasts for a second
return () => {
clearInterval(interval);
};
}, []);
console.log(timer) //this will be decreasing every second
I'm using PHP over IIS 7.5 on Windows Server 2008.
My web application is requesting repeatedly with Ajax in the background 3 different JSON pages:
page 1 Every 6 seconds
page 2 Every 30 seconds
page 3 Every 60 seconds
They retrieve data related with the current state of some tables. This way I keep the view updated.
Usually I have no much trouble with it, but lately I saw my server saturated with hundreds of unanswered requests and I believe the problem can be due to a delay in one of the request.
If page1, which is being requested every 6 seconds, needs 45 seconds to respond (due to slow database queries or whatever), then it seem to me that the requests start getting piled one after the other.
If I have multiple users connected to the web application at the same time (or with multiple tabs) things can turn bad.
Any suggestion about how to avoid this kind of problem?
I was thinking about using some thing such as ZMQ together with Sockets.io in the client side, but as the data I'm requesting doesn't get fired from any user action, I don't see how this could be triggered from the server side.
I was thinking about using some thing such as ZMQ together with Sockets.io in the client side...
This is almost definitely the best option for long-running requests.
...but as the data I'm requesting doesn't get fired from any user action, I don't see how this could be triggered from the server side.
In this case, the 'user action' in question is connecting to the socket.io server. This cut-down example is taken from one of the socket.io getting started docs:
var io = require('socket.io')(http);
io.on('connection', function(socket) {
console.log('a user connected');
});
When the 'connection' event is fired, you could start listening for messages on your ZMQ message queue. If necessary, you could also start the long-running queries.
I ended up solving the problem following the recommendation of #epascarello and improving it a bit if I get no response in X time.
If the request has not come back, do not send another. But fix the serverside code and speed it up.
Basically I did something like the following:
var ELAPSED_TIME_LIMIT = 5; //5 minutes
var responseAnswered = true;
var prevTime = new Date().getTime();
setInterval(function(){
//if it was answered or more than X m inutes passed since the last call
if(responseAnsswered && elapsedTime() > ELAPSED_TIME_LIMIT){
getData()
updateElapsedTime();
}
}, 6000);
function getData(){
responseAnswered = false;
$.post("http://whatever.com/action.json", function(result){
responseAnswered = true
});
}
//Returns the elapsed time since the last time prevTime was update for the given element.
function elapsedTime(){
var curTime = new Date().getTime();
//time difference between the last scroll and the current one
var timeDiff = curTime - prevTime;
//time in minutes
return (timeDiff / 1000) / 60;
}
//updates the prevTime with the current time
function updateElapsedTime(){
prevTime = new Date().getTime();
}
This is a very bad setup. You should always avoid polling if possible. Instead of sending request every 6 seconds from client to server, send data from server to the clients. You should check at the server side if there is any change in the data, then transfer the data to the clients using websockets. You can use nodejs at the server side to monitor any changes in the data.
I am writing a NodeJS push notification server for iOS and Android. Currently, once I get the device tokens I save them in a local MongoDB database and then fire notifications when there is a change. The problem is, that the database where the "change"(information is added) happens isn't my own. It's a third party's server. So the way I am aware of the change in the server is by using an API provided by the third party. My current solution is using setTimeout to make a request every X minutes to check for a change and then firing a notification based on that. The shorted interval is 10 minutes and the longest one is 1 hour. I change the intervals
dynamically through out the day based on time. My question(s) is (are),
1.) Is the setTimeout method the best possible solution to this problem? If not what else can I use?
2.) Is there any way I can implement Web Sockets in this scenario?
3.) If setTimeout is the only option, what kind of problems should I expect to run into?
This what the current function looks like
function start_notifications_server_driver() {
if(current_user_info.num_sent <= current_user_info.frequency){
//I removed the interval object on here because it's quite large and would take up space here
for(var i = 0; i < intervals.length; i++){
if(check_if_time_between(intervals[i])){
if(dev_mode) console.log("Returned true for", intervals[i]);
temp_interval = intervals[i].frequency;
break;
}
}
check_updates_for_channels_driver();
setTimeout(start_notifications_server_driver, temp_interval);
console.log("Time Interval changed to now", temp_interval);
}
}
Basically, I am designing a quiz application with limited time. Use selects answer to a question and the next question loads using an Ajax request. All questions must be answered within a time frame of, say 2 minutes.
A clock ticks away to show how much time is left and as soon as it hits 0, results are shown. Now since the timer will be implemented using window.setTimeout(), it is possible that the value of timer variable be modified using an external bookmarklet or something like that. Anyway I can prevent this? I think this is implemented on file sharing sites like megaupload. Any forgery on the timer variable results in request for file being rejected.
Have .setTimeout() call an AJAX method on your server to synch time. Don't rely on the client time. You could also store the start time on the server for a quiz, and then check the end time when the quiz is posted.
You need to add a validation in your server side. When the client want to load the next question using an Ajax request, check whether deadline arrived.
The timer in client side js just a presention layer.
If the function runs as a immediately called function expression, then there are no global variables and nothing for a local script to subvert. Of course there's nothing to stop a user from reading your code and formulating a spoof, but anything to do with javascript is open to such attacks.
As others have said, use the server to validate requests based on the clock, do not rely on it to guarantee anything. Here's a simple count down that works from a start time so attempts to dealy execution won't work. There are no global variables to reset or modify either.
e.g.
(function (){
// Place to write count down
var el = document.getElementById('secondsLeft');
var starttime,
timeout,
limit = 20; // Timelimit in seconds
// Function to run about every second
function nextTick() {
var d = new Date();
// Set start time the first time
if (!starttime) starttime = d.getTime();
var diff = d.getTime() - starttime;
// Only run for period
if (diff < (limit * 1000)) {
el.innerHTML = limit - (diff/1000 | 0);
} else {
// Time's up
el.innerHTML = 0;
clearTimeout(timeout);
}
}
// Kick it off
timeout = window.setInterval(nextTick, 1000);
}());