I wrote a server and locally everything works great, but after deploy it to heroku setTimeout is executed instantly and without delay. Tried to deploy setTimeout(openCard(buttonIndex), 1000), timeoutID is global variable. Aclually don't what to do
const clickButton = (client, buttonIndex, time) => {
if(!(users[client.id])['isMaster']) {
if(room.teamTurn === (users[client.id])['team'] && !arrayToPlay[buttonIndex].isClicked && room.gameStarted && !globaleTime.MasterTurn) {
if(room[room.teamTurn].length > 1) {
addChosenWord(client,buttonIndex);
}
wordChosen = chosenWordCorrect() ? buttonIndex : null;
io.emit('wordChosen', wordChosen);
if(wordChosen !== null){
clearTimeout(timeoutID);
const date = new Date();
const localTimeOffset = date.getTimezoneOffset() * 60000;
const offset = date.getTime() - localTimeOffset - time;
timeoutID = setTimeout(()=>openCard(buttonIndex), 1000 + offset);
} else {
clearTimeout(timeoutID)
io.emit('room', room);
}
} else {
io.emit('buttonClicked', buttonIndex,client.id);
}
}
}
I noticed that you have in the code setTimeout(() => openCard(buttonIndex), 1000 + offset); but in your ask setTimeout(openCard(buttonIndex), 1000).
Check if the openCard is inside an arrow function in the setTimeout.
date.getTime() returns a time stamp based on the UTC time zone ref.
If the time argument comes from a date.getTIme call on the front end, the server should not be adjusting it for the time zone of the server.
Solution: remove local time zone adjustment on the server.
If the front end is sending the time based on local time, it would also need to notify the server what time zone it is in.
Solution: change the time sent from the client to use UTC time zone and remove local time zone adjustment on the server.
Most likely the code works locally because the server's time zone is the same as the client's, and deploying it to a server in another time zone breaks the current logic for calculating the timer millisecond count.
Assuming that time is in the UTC time zone, and that the objective is to open a card a second after clicking the button taking into account the time the request takes to reach the server, this example attempts to calculate a suitable delay:
if(wordChosen !== null){
clearTimeout(timeoutID);
// time in UTC zone:
let requestTime = Date.now() - time;
requestTime = Math.max( 20, requestTime); // not too low or negative
const responseFactor = 0; // 0 to ignore;
let delayTime = 1000 - requestTime - requestTime*responseFactor;
delayTime = Math.max(0, delayTime); // non negative
timeoutID = setTimeout(()=>openCard(buttonIndex), delayTime);
}
Set responseFactor to a number between 0 and 1 to include an estimate of the response time based on the request time.
Related
I'm trying to calculate time when user open a specific screen,When he enters in the screen the the time starts and when I exit from the screen the time stops and gives the time spend on the screen
here is my code:
componentDidMount = () => {
let date = new Date();
let hours = date.getHours();
let minutes = date.getMinutes();
let seconds = date.getSeconds();
this.setState({
startHour: hours,
startMin: minutes,
startSeconds: seconds,
});
}
Here is ComponentWillunmount
componentWillUnmount() {
let date = new Date();
let endHours = date.getHours();
let endMinutes = date.getMinutes();
let endSeconds = date.getSeconds();
console.log(`${endHours}:${endMinutes}:${endSeconds}`);
console.log(
`${this.state.startHour}:${this.state.startMin}:${this.state.startSeconds}`,
);
}
When he enters in the screen the the time starts and when I exit from
the screen the time stops and gives the time spend on the screen
It's a very important Feature Request by many for web 2.0 applications. So, I write a detailed, working and simple solution on the subject here.
You are requesting a feature already created for this workflow. It's a plugin you can include in any website. It's none other than time-on-site tracking in timeonsite.js
Look at the following code (Use latest version; don't just copy/paste),
<head>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/timeonsite/1.2.0/timeonsitetracker.js"></script>
<script>
var config = {
// track page by seconds. Default tracking is by milliseconds
trackBy: 'seconds',
trackHistoryChange: true, //Single-page React/Angular app
callback: function(data) { /* callback denotes your data tracking is real-time */
console.log(data);
var endPointUrl = 'http://example.com' //Replace with your actual backend API URL http://localhost/tos
if (data && data.trackingType) {
if (data.trackingType == 'tos') {
if (Tos.verifyData(data) != 'valid') {
console.log('Data abolished!');
return;
}
}
// make use of sendBeacon if this API is supported by your browser.
if (navigator && typeof navigator.sendBeacon === 'function') {
data.trasferredWith = 'sendBeacon';
var blob = new Blob([JSON.stringify(data)], {type : 'application/json'});
navigator.sendBeacon(endPointUrl, blob);
}
}
}
};
var Tos;
if (TimeOnSiteTracker) {
Tos = new TimeOnSiteTracker(config);
}
</script>
</head>
Then, when you refresh, reload or navigate the React app page,
You'll see following object directly saved into your table/printed in browser console. Select "persist" in logs,
{
TOSId: 1129620185532,
TOSSessionKey: "14802525481391382263",
TOSUserId: "anonymous",
title: "Test application - Home page",
URL: "http://nature-blogs/pages/home.php"
entryTime: "2021-11-27 13:15:48.663",
currentTime: "2021-11-27 13:17:31.663",
timeOnPage: 103,
timeOnSite: 103,
timeOnPageTrackedBy: "second",
timeOnPageByDuration: "0d 00h 01m 43s",
timeOnSiteByDuration: "0d 00h 01m 43s",
trackingType: "tos",
}
As you can see, the actions
"entryTime" is captured
"exitTime" is captured in seconds/milliseconds depending upon configuration
"type:time_on_site" is captured
"timeOnPage" is captured // individual page time
"timeOnSite" is captured // session overall page time
What else you need? Since it's stored in SQL DB table, you can do analysis/reporting queries yourself. The same is the case for NoSQL as well. Timeonsite.js is supporting both RDBMS and NoSql DB types.
On top of it, 1.Minimize tab, 2.Inactive tab and 3.Switch tab's idle time are all computed and ignored automatically by the tracker itself.
The only thing to note in configuration part is,
trackHistoryChange: true
If the page routing depends on Location Hash or also known as single-page app, include this setting. On the other hand if your web application is a normal page like Wikipedia, avoid setting this line. You are done. For showing the real-time stay time on screen, check this SO post. It's using Jquery to show the results. You can customize it for your React app.
This tracker can be plugged-in in any library not only in React app but also Angular, Jquery, MooTools etc. since it's plain vanilla JS library.
Let me know if you need more input on the subject. I can assist you on this.
I'm not a react dev but this is fairly simple and this would be the approach.
componentDidMount = () => {
/* On init set the start time
Also: multiplying new Date() by 1 will return a timestamp
*/
this.startTime = new Date() * 1;
}
componentWillUnmount() {
/* Then on view destroy set the endTime */
let endTime = new Date() * 1;
/* Subtract the end time with start time, since endTime has greater value. The result
is the difference between start and end time in milliseconds.
*/
let elapsed = endTime - this.startTime;
/* The result is in milliseconds so:
elapsed / 1000 -> is seconds
elapsed / 1000 / 60 -> is minutes
etc.
*/
);
I agree with #masterpreenz
componentDidMount = () => {
this.startTime = new Date() * 1;
}
componentWillUnmount() {
let endTime = new Date() * 1;
let elapsed = endTime - this.startTime;
$('viewPageStayTime').html('You spent '+elaspsed+ ' duration.');
);
I have a simple webworker which keeps the current time of timezone using setInterval
setInterval(() => {
userTimezoneTimestamp = userTimezoneTimestamp + 1000
postMessage(userTimezoneTimestamp);
}, 1000);
It works fine until I put my machine on sleep mode. When I restart the machine from sleep mode, the time which I get from this worker is older.
How can I restart my web worker only when the machine starts up from sleep mode?
There doesn't seem to be any DOM event letting us know about that event.
On my notebook Chrome does fire a non-standard orientationabsolutechange event, but I think not all notebooks have orientation aware hardware and already just Firefox on the same machine doesn't fire it.
But for what you want (an always up to date offset from an API served timestamp), you don't need a WebWorker at all, nor any timer, the computer comes with a good one and not only will it still be up to date after computer sleep, it will even be more precise than your interval which can suffer from time-drift.
All you need is to store the offset you got from your API and the computer's time you received it. Then you just need to get the difference between now and that time of reception and you can easily get your updated offset.
OP noted that they are afraid their users modify their computer's time to an earlier date, thus messing up with Date's values while the page is running. This can be detected. All it takes is to store the last value, and check if the difference with the current one is negative.
( async () => {
const offset_from_API = await getOffsetFromAPI();
const time_received = Date.now();
let last_time = time_received;
const getUpToDateOffset = () => {
const now = Date.now();
// Anti-Back-Time-Travelling check
// (it's a good idea to poll this method quite often too update `last_time`)
if( now - last_time < 0 ) {
throw new Error( 'cheater detected' );
}
last_time = now;
return offset_from_API + (now - time_received);
};
// to compare we will also use an incrementer
let incremented = offset_from_API;
setInterval( () => {
incremented += 1000;
console.clear();
console.log( 'incremented', incremented.toLocaleString( 'en-US' ) );
console.log( 'difference ', getUpToDateOffset().toLocaleString( 'en-US' ) );
}, 1000 );
} )();
function getOffsetFromAPI() { return 1234567; }
setInterval(() => {
/*handle userTimezoneTimestamp stuff every N miliseconds */
}, N);
setInterval(() => {
userTimezoneTimestamp = userTimezoneTimestamp + 1000
postMessage(userTimezoneTimestamp);
}, 1000);
I am working on a tool that require to measure certain amount of time (for example 2 minutes) since user interaction with a tool, this time also needs to be displayed for the user.
I started simple server loop for this reason:
setInterval(function() {
measure.time();
}, 10);
i created a code for to calculate:
this.reset = 0;
this.step = 100 // 10 ms server loop, adds 1 to reset === 100 is 1 second
this.time = function() {
if(this.reset === this.step) {
console.log('SPAWN', new Date());
this.reset = 0;
}
this.reset++;
};
this is the result of my approach:
The idea is to show clock for the user and update it every second, but it skips seconds rather often, what am i doing wrong?
I have a countdown that every 30 seconds restarts the countdown.
var interval = 31000;
function reset() {
localStorage.endTime = +new Date + interval;
}
if( ! localStorage.endTime ) {
reset();
}
setInterval( function() {
var remaining = localStorage.endTime - new Date;
if( remaining >= 0 ) {
$('#timer').text( Math.floor( remaining / 1000 ) );
} else {
reset();
}
}, 100 );
I need to find a way to countdown across the whole server. So every viewer will experience the same countdown. Any ideas?
You can put that code in IIF in separate js file and inslude it on every page of your site and it should work cause local storage variables are available in every page in you site.
(function(){ /*... your code ...*/ })();
If you want to implement it on server side, so you can do it same way but instead of only setting value in local variable you also have to post it on server and retrieve when IIF invokes for first time (using AJAX).
(function(){ /*get variable end time and
in callback set it to local storage ... your code ...
in reset function post new value of end time on server */
})();
Is there some window variable in javascript that I can use or a way to use a timer to track elapsed time without using a date object? flash.utils.getTimer works great in the flash version of this application and I'm trying to port it to javascript. I can't risk changes to the system clock causing security problems, so I don't want to use the Date object.
I have a servertimestamp and I would like to create a timer that is independent of the operating system time to calculate the current server time. I'll use this calculated value to allow different operations during windows on the server time. I'm not concerned about javascript hacking as I know there's no security there, but I would like to prevent the casual user from messing around with the availability of certain features.
Thanks
Added for clarification:
This project relates to live video events. The live video has a start time relative to the server and through another webservice I am able to grab the server time. What I need to do is to maintain this server time on the client machine independently of the user's local time to determine when the live stream should start and stop on the client. So the problem isn't really the format that I store the server time, it's how do I get the elapsed time from when I grabbed the server time without using a date object.
You could create your own timer object:
function Timer(init, precision) {
var start = time = new Date(init || null).valueOf(),
precision = precision || 100;
setInterval(function () { time += precision; }, precision);
this.elapsed = function() { return time - start; };
this.getDate = function() { return new Date(time); };
}
and use it:
var t = new Timer(); // default timer
/* ... do things ... */
alert( t.elapsed() ); // a millisecond value
alert( t.getDate() ); // a Date object
Use the init parameter to start the timer with any given date value you prefer.
You could have the server send the server time and store it in a javascript Date variable. Then you can base your calculations on this variable knowing that it will be the server time and won't be dependent on the client system clock. As far as executing some javascript method at regular intervals is concerned you could use the setTimeout and setInterval methods.
This function doesn't work well, because it accumulates error from the interval, the interval is not completely precise it depends on javascript cycles.
function Timer(init, precision) {
var start = time = new Date(init || null).valueOf(),
precision = precision || 100;
// here's where the error acummulates
setInterval(function () { time += precision; }, precision);
this.elapsed = function() { return time - start; };
this.getDate = function() { return new Date(time); };
}
I tested with this script:
const t = new Timer();
setTimeout( () => {
console.log(t.elapsed());
}, 1000 * 30);
// it returns 28800 (200ms of error, and is accumulative)
My improved versiĆ³n:
function Timer(init, precision) {
const baseTime = new Date().valueOf();
let time = init ? new Date(init).valueOf() : baseTime;
let delta = baseTime - time;
const start = time;
precision = precision || 100;
const interval = setInterval(() => time = (new Date()).valueOf() - delta, precision);
this.elapsed = () => time - start;
this.getDate = () => new Date(time);
this.getTime = () => time;
this.stop = () => clearInterval(interval);
}
const testTime = 1000 * 60;
const t1 = new Timer();
setTimeout( () => {
console.log(t1.elapsed(),t1.getDate());
t1.stop();
}, testTime);
// 59988 Tue Mar 23 2021 11:28:42 GMT-0300 (Chile Summer Time)
const t2 = new Timer('Jan 01, 2020');
setTimeout( () => {
console.log(t2.elapsed(), t2.getDate());
t2.stop();
}, testTime);
// 59988 Wed Jan 01 2020 00:00:59 GMT-0300 (Chile Summer Time)
const t3 = new Timer('Jan 01, 2020', 500);
setTimeout( () => {
console.log(t3.elapsed(),t3.getDate());
t3.stop();
}, testTime);
// 59937 Wed Jan 01 2020 00:00:59 GMT-0300 (Chile Summer Time)