I have been recently working on the timeout function (used javascript - setInterval). I did test it, it worked exactly the way I want apart from one tiny detail. Whenever a logged in user sleeps the computer, the session is still active and timeout keeps counting the time. Consequently, after waking the PC up, let's say after 40 min, the timeout says e.g. -10 min and the user is still logged in. If he clicks anything or refresh the page, the service will refresh and the timeout is being restarted to the initial value like nothing happened (user is still logged in). Is there a way of making sure that the user is going to be logged out after waking the PC up?
Thanks a lot in advance!
If I understand your problem, the solution could be to call a script in ajax when the timeout has a value of 0, which will log out the user and then you could refresh the page, the all thing in javascript
Rather than using setTimeout/setInterval for you logout directly, perhaps try something like this:
var targetTime = moment(new Date()).add(5 ,'s');
var intervalHolder = {};
console.log("go")
intervalHolder.interval = setInterval(() => {
if (moment(new Date()).isAfter(targetTime)) {
console.log('TimedOut');
clearInterval(intervalHolder.interval);
}
},1000);
<script src="https://momentjs.com/downloads/moment.js"></script>
Related
I have an auction site in MERN stack with socket.io and i seem to have this unsolvable problem which i think is related to browsers and basic JS
Flow:
whenever a product is added by admin, socket broadcasts it with all
of details (including time )to all clients.
the clients can bid on them and stuff.
if a user refreshes the screen , it requests the socket for latest
product time and starts countdown from that time.
Everything is fine except some times react-countdown is lagging 0.5 second to 1 second behind whenever page is refreshed (please note that problem does not occur when opening same auction on new tab)
Note: i have also tried self made Countdown timer using setInterval but the problem does not go away
I am seeking assistance with this problem and am willing to compensate someone for their time and efforts to work with me directly to resolve it. Any help would be greatly appreciated.
Using setInterval and setTimeout means you are at the mercy of the browser. Browsers will often slow down the execution of these if some other process is happening and return to it once that's done, or if you switch away to another tab, they will purposefully reduce the tick rate. The level of accuracy you require is not easily achieved.
Firstly, I would suggest that getting the time it ends, then finding the difference between then and now, and counting down from this value with 1s increments will aggravate this problem. If each "tick" is off by even a small amount, this will accumulate into a larger error. This is probably what the library is doing by default. It may have also been what you were doing when you made your own timer, but I'd need to see it to confirm.
Instead, you need to store the time it ends passed from the socket (or keep it in scope like below) and on each "tick", work out the difference between then and now, every single time.
You could do this by using react-countdown in controlled mode and doing this logic in the parent.
I've made up a function here which would be the thing that receives the time from the socket -- or it's called from it. Its pseudo-code.
const timer = useRef(null)
const [timeLeft, setTimeLeft] = useState(null) // In seconds
const handleSocketReceived = (({endTime}) => {
timer.current = setInterval(() => {
const newTimeLeft = endTime - Date.now() // Pseudo code, depends on what end time is, but basically, work out the diff
setTimeLeft(newTimeLeft)
}, 100) // Smaller period means more regular correction
}, [])
// ...
useEffect(() => {
return () => clearInterval(timer.current)
}, [])
// ...
<Countdown date={timeLeft} controlled={true} />
User login is managed with JWT stored in localStorage for my Website.
And within login function, setTimeout function exists and it clears the localStorage, when token expiration time has come.
But It doesn't work when the device has been to sleep mode. When it awakes, the time of clearing localStorage has already passed and logout function is not being called as I expected.
So if there is some way to run the function that are queued with 'setTimeout()', I would like to call it when device is awake from sleep mode.
Is it possible to call the functions that already has passed the time of setTimeout?
No, but you can save the timeout to a variable and check if it's been cleared, and manually call function as needed:
const func = () => {
console.log("hi")
}
const timeout = setTimeout(func, 1000)
// You'll have to implement a computer wake checker
onComputerWake(() => {
if (!timeout) func()
})
But as another user mentioned in the comments, this is a terrible idea. JWTs have a built-in expiration. You should just have the server return 401, and redirect the user to the sign-in page if you receive 401 in your frontend.
I'm working on a small project, that combines Java(servlets) with some web elements. I've got a Java back-end that deals with registration and login. When the user has logged in, he/she arrives at the dashboard where a timer awaits them.
The timer should be set at 25 minutes and when the user presses 'start', it should start counting down to zero. When zero has been reached, I want the timer to save the timestamps (begin/end) to MySQL and automatically start a 5 minute timer.
I've been looking on Google for quite some time. jQuery seems the easiest option, but I'm genuinely struggling getting this started.
Is there anyone who could help me?
Perhaps guide me on the right path or (if you have time) have a little coding session?
On waiting page use Javascript:
var timeleft = 1500; // seconds left
var timer = setInterval(function () {
timeleft--;
// optional: update HTML element here
if (timeleft == 0) { saveTimestamp(); clearInterval(timer); }
}, 1000); // run every second
Then make saveTimestamp function either redirect browser to another page or make ajax call to sync with server.
On server, make a check if user reached this point after less than 25 minutes, and if he didn't (no cheating), perform standard writing to SQL (I can't help you much with server-side, as I've never worked with Java servlets).
I have used a few of the jquery keepalive session plugins with out problem.
I have been asked for something a bit different.
We have some forms (built before I started here) that are fairly large and users work in them for a while. The page is never refreshed, so they click save and the session is expired and redirect to the login page.
I suggested one of these plugin, that just prompt the user a few minutes before the session expires which would make an ajax call to keep the session alive.
However, they said, will what if they dont see the prompt and miss it all together and logs them out.
They would like me to check
Has the user had any interaction with the page in the last 5 minutes.
If Yes=Ajax call to keep alive the session, and reset timer.
if No, continue to wait until we get within 2 minutes of session time out and prompt user.
They are trying to avoid the prompt.
Is there anyway with JS/Jquery to know if the page has had any client side interaction?
Rather than using a timer to check if they've had any interaction in the last 5 minutes, couldn't you just send your keepalive any time the form has changed? It would eliminate a need for a timer loop and a small payload ajax call just to keep the session alive shouldn't hurt performance at all.
If you still want to keep the timer loop, I would still recommend using the change event on your form elements. Changing the form implies they're interacting with it, and I think that satisfies their requirement.
Edit: Update to use timer
var idle = true;
function finalIdleCheck(prompt){
if(idle){
if(prompt){
alert("last warning!");
}
//Tighten the idle check time loop; may even want to go < 30s
setTimeout(finalIdleCheck, 30*1000);
} else {
//Ajax stuff to keep session alive
idle = true; //Reset idle flag
}
}
function checkIdle(){
if(idle){
//Warn them
alert("You've been idle");
setTimeout(function(){
finalIdleCheck(true);
}, 60*2*1000);
} else {
//Ajax stuff to keep session alive
idle = true; //Reset idle flag
}
}
$(document).ready(function(){
$("form input").on("change", function(){
idle = false;
}
setTimeout(idleCheck, 60*5*1000);
}
In a modern web browser, suppose I do a setTimeout for 10 minutes (at 12:00), and 5 minutes later put the computer to sleep, what should happen when the system wakes up again? What happens if it wakes up before the 10 minutes are up (at 12:09) or much later (at 16:00)?
The reason I'm asking is because I'd like to have a new authentication token requested every 10 minutes, and I'm not sure if the browser will do the right thing and immediately request a new token if it wakes up after a long time.
Clarifications: I don't wan't to use cookies - I'm trying to build a web service here; and yes, the server will reject old and invalid tokens.
As far as I've tested, it just stops and resumes after the computer wakes up. When the computer awakes the setInterval/setTimeout is unaware that any time passed.
I don't think you should rely on the accuracy of setTimeout/Interval for time critical stuff. For google chrome I discovered recently that any timeout/interval (that is shorter than 1s) will be slowed down to once a second if the tab where it's activated looses focus.
Apart from that the accuracy of timeouts/intervals is dependent on other functions running etc. In short: it's not very accurate.
So using interval and timeouts, checking the time against a starttime within the function started by it would give you better accuracy. Now if you start at 12:00, the computer goes to sleep and wakes up at 16:13 or so, checking 16:13 against 12:00 you are certain you have to renew the token. An example of using time comparison can be found here
Compare current datetime against datetime when the page was loaded, like so:
//Force refresh after x minutes.
var initialTime = new Date();
var checkSessionTimeout = function () {
var minutes = Math.abs((initialTime - new Date()) / 1000 / 60);
if (minutes > 20) {
setInterval(function () { location.href = 'Audit.aspx' }, 5000)
}
};
setInterval(checkSessionTimeout, 1000);
Here is my code :
<!doctype html>
<html>
<body>
<input type="button" name="clickMe" id="colourButton" value="Start Timer" onclick="setTimeout('alert(\'Surprise!\')', 120000)"/>
</body>
<script>
</script>
</html>
I have taken three scenarios that might answer the question.
Scenario 1: At 00 Seconds click on 'Start Timer' button . At 25 seconds computer falls asleep.
At 1min 40 seconds wake up computer.
At 2mins Alert is displayed.
Scenario 2 : At 00 Seconds click on 'Start Timer' button . At 26 seconds computer falls asleep.
At 3 mins, I wakeup the computer. The Alert is displayed.
Scenario 3 : This one is truly astounding.
<input type="button" name="clickMe" id="colourButton" value="Start Timer" onclick="setTimeout('alert(\'Surprise!\')', 600000)"/>
At 00 Seconds I click on 'Start Timer' button.
At around 1min 30 seconds the computer is on hibernate mode (my pc takes a minute to initiate hibernate)
At 8 mins I turn the laptop on.
At 10 mins exactly, the alert pops up.
PS: This is my first ever comment on Stack Exchange. I prefer to execute code and view results rather than infer from theory.
The behavior is based on both the browser and the operating system. The OS handle sleep and individual apps often don't account for it.
What will most likely happen is that the OS will come back up with the same time remaining on the timer as when it was shut down. The other possibility is that it won't fire at all.
If it is really a concern, you will probably want to be better safe than sorry and store a time stamp of when the token was initialized and use setInterval to check it periodically (say twice a minute).
However, security should not be just a client side thing. Make sure that your server throws an error if an old / invalid token is used and that the Ajax behaves appropriately in response.
[edit]
I agree with the other post that it might fire immediately on the next tick. Resig's blog post is very good.
Behaviour of JavaScript timers (setTimeout) in several scenarios.
When the thread is free and the timeout fires: The timer is fired immediately after the timeout. It might have certain imprecision of about 0-5 ms (typical scenario).
When the thread is super busy (huge loop) long enough to pass the timer timeout: The timer will be executed immediately after the thread is freed.
When there is an alert: Same behaviour as 2.
When the thread is paused because our laptop went to sleep: I have seen several things. But most common is total inaccuracy and ignore of the time spent during sleeping.
Since timers in JavaScript are based on CPU ticks, and the CPU is sleeping, then the timer is completely paused and resumed as 'since nothing would have happen'.
Based on Ben's answer, I created the following util. You can tweak the sampling duration, however I use it just like this for token refreshing:
const absoluteSetInterval = (handler, timeout) => {
let baseTime = Date.now();
const callHandler = () => {
if (Date.now() - baseTime > timeout) {
baseTime = Date.now();
handler();
}
};
return window.setInterval(callHandler, 1000);
};
const absoluteClearInterval = (handle) => window.clearInterval(handle);
In John Resig's blog the timers are said to be using "wall clock". I believe that the events will fire immediately after the machine is resumed because setTimeout() doesn't guarantee an execution is a specific point in time but as soon as possible after the specified interval. However, I haven't checked it myself.