2

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?

Harshal Ringe
  • 51
  • 2
  • 6
  • 1
    for every X seconds also set interval for `userTimezoneTimestamp`variable. This sync `userTimezoneTimestamp` when machine starts up from sleep mode. – hakki Mar 19 '20 at 09:27
  • 1
    I doubt that what you ask is possible. The browser is privileged to suspend any open tab and it's workers at any time.\ – Tomáš Zato Mar 19 '20 at 13:25
  • I don't get what you are doing, why and how what you ask for would help. Your worker should restart at least at the same time as your main page. Is it not the case? What are you exactly doing, what exact behavior do you have and what should it be? Here is a small playground you can edit to make your case clearer. https://jsfiddle.net/m9tjo6h5/ – Kaiido Mar 23 '20 at 10:24
  • Hi @Kaiido, I am maintaining a user's timezone's current timestamp using webworker exactly like you did in Jsfiddle. But webworkers stop working as soon you put PC on sleep mode. When I start PC the timestamp i'm getting from webworker is old. Now I wanted a window event which would let me know that the application resume from sleep mode. As Reinstate Monica said, I don't think it is possible – Harshal Ringe Mar 24 '20 at 05:33
  • Why do you want such an event? How do you think that would help? What does "is old" mean? How do you get the initial timestamp? – Kaiido Mar 24 '20 at 05:50
  • Hi @Kaiido, I get the initial timestamp from an API, and I maintain it on the browser using setInterval in webworker. But webworker stops executing when we put a computer on sleep mode. When I log in again the time inside webworker is past time and at that time I want to get the current timestamp from API again so that I can maintain the current timestamp. – Harshal Ringe Mar 25 '20 at 08:39

2 Answers2

2

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; }
Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • Thanks @Kaiido, In our application, we can't reply on client time. Date.now() function returns the computer's time and which we can be easily set as a past time. If user changes computer time to past time, Using Date.now() function we won't get the right time. That why we were getting current time from the server and maintaining it on the client-side using setInterval inside web worker. Everything was working fine until this sleep mode scenario – Harshal Ringe Mar 25 '20 at 12:10
  • @HarshalRinge edited my answer. That event (when the user sets their clock to a previous date) can be detected. Computer's wake on the other hand can't. – Kaiido Mar 27 '20 at 09:48
  • Thank you so much @Kaiido, performance.now() was useful in my case. I have changed my code and I'll update as an answer. Thanks a bunch!! – Harshal Ringe Mar 29 '20 at 16:41
  • performance.now will "pause" when the browser sleeps, finally not a good odea, sorry. Checkong of user changed their clock settings os the most reliable way – Kaiido Mar 29 '20 at 22:22
  • Hi @Kaiido, What do you mean by browser sleeps? I tested it by changing machine time to past time and I also checked it by putting the machine on sleep mode. In both cases, it is working fine. When the system wakes up from sleep mode, It gives correct value in performance.now(). Thanks :) – Harshal Ringe Mar 31 '20 at 07:11
  • @HarshalRinge it shoudln't. When I tried putting my computer to sleep, performance.now just stuck to where it was until the computer awakes. The solution in the current answer is the only stable solution I could think of. – Kaiido Mar 31 '20 at 07:20
  • Hi @Kaiido, I have created a sample example in [fiddle](https://jsfiddle.net/2to5wb9s/7/) I ran it, after 10 seconds, I put my machine on sleep mode for 1 min. then I start the machine, In fiddle, it was showing exact time .i.e. (10 Seconds + 60 Seconds ). Can you please give it a try because it is working in case? – Harshal Ringe Mar 31 '20 at 07:58
  • @HarshalRinge I fear your computer didn't really went to sleep. Try this fiddle: https://jsfiddle.net/x9zwnva3/ on my computer (and phone), the simple increment and performance.now stay synced. – Kaiido Mar 31 '20 at 08:28
-1
setInterval(() => {
        /*handle userTimezoneTimestamp stuff every N miliseconds */
    }, N);


setInterval(() => {
        userTimezoneTimestamp = userTimezoneTimestamp + 1000
        postMessage(userTimezoneTimestamp);
    }, 1000);
hakki
  • 6,181
  • 6
  • 62
  • 106