moribvndvs / ng2-idle

Responding to idle users in Angular (not AngularJS) applications.
https://moribvndvs.github.io/ng2-idle
Apache License 2.0
315 stars 128 forks source link

idleTimeoutWarning lags wall-clock when tab is in background) #157

Closed BoilerTom90 closed 7 months ago

BoilerTom90 commented 2 years ago

NOTE: Due to limited time constraints and resources, we ask that you please use Stack Overflow or similar to troubleshoot or ask general questions, and not use bug reports to solicit help setting up your app.

Describe the bug When the application tab is in the background, the idleTimeoutWarning method lags the wall-clock. For example, If I set the the timeout parameter to a 10 minutes, once the idle period has started, if the tab is in the background, it may take up to 10 minutes for the idleTimeout callback to get invoked.

More specifically, if the idleStart handler occurred at say 1:00pm, and I've configured the timeout to be 10 minutes, if the browser tab is in the background, the idleTimeout event will not occur until much after 1:10pm.

Note: the idleTimeoutWarning event is fired "mostly" on time, but the timeout value passed to the callback is what is lagging.

To Reproduce

Use the DEFAULT_INTERRUPTSOURCES. Set the idle time to a really small value (say 1 second), and the timeout to a value such as 10 minutes. Start up two or more apps Immediately upon restarting the apps, minimize the browser window. After 10 minutes you should expect to have received the idleTimeout event, but it will occur much later. Also, it's likely that not all browser tabs will receive the event at the same time. I have seen the idleTimeout occur as much as 2x later than it should have.

Expected behavior I would expect the idleTimeout event to be emitted within a second or two of the parameter setting.

Please tell us about your environment

Additional context Add any other context about the problem here.

elaihau commented 2 years ago

This bug can also be reproduced in my project.

codeix commented 2 years ago

We also can confirm this issue in our project.

Is there a workaround?

zachsteffens commented 2 years ago

Is there still no solution for this?

onIdleStart does not fire until the browser window is active.

moribvndvs commented 2 years ago

many modern browsers suspend or slow down timers and other JS execution when in the background. I’m not aware of any way to influence that, the best I can do is recommend a way to trigger the idle check when the browser is activated/focused/visible again. See this comment https://github.com/moribvndvs/ng2-idle/issues/158#issuecomment-920194789

michaelmarcuccio commented 2 years ago

I am also looking to solve this scenario consistently.

zachsteffens commented 2 years ago

The solution I ended up with was to use web workers to take over for the setTimeout/setInterval calls. After a fair amount of testing, it appears that web workers are not affected by the browser de-prioritizing code execution for minimized or background tabs. Easiest solution for me was to use HackTimer. This resulted in the initial idle timer firing reliably. Unfortunately, the setTimeout timer that activates after the idle period (to warn users they are about to get signed out) did not work so reliably, I'd set it for 90 minutes idle, and 1 minute warning. 90 mins would fire right on time and the 1 minute would be anywhere from 2 to 15 mins before it completed.

I just ended up abandoning the warning period. I figured if it was ultimately necessary, I could have forked this repo and attempted to write a custom web worker workflow. But I'm not confident you'd be able to get the warning timer working properly seeing as it involves multiple callbacks to the observable (back and forth between the web worker and the main thread) but who knows. Hope this helps.

RogueJay commented 2 years ago

I was just looking at this and was thinking a potential code solution would be...

When the tab does become active, it does at least start the timeout at that point. However, the countdown starts from the complete timeout period. Instead, if the code at least took into account how long ago the expiry diff was, then at least the countdown would start at the correct wall clock time (or force an immediate timeout)

moribvndvs commented 7 months ago

See if #131 resolves the issue.