Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to replace short (less than a minute) setTimeouts in Event Page Extensions

The documentation about transitioning from background persistent extensions to non persistent Event Pages, states:

If your extension uses window.setTimeout() or window.setInterval(), switch to using the alarms API instead. DOM-based timers won't be honored if the event page shuts down.

Fair enough, but the alarms API documentation states:

when can be set to less than 1 minute after "now" without warning but won't actually cause the alarm to fire for at least 1 minute.

So, i have a short setTimeout in my EventPage, it takes 5s, how can i ensure it completes, if i can't use an alarm for those short times. Setting a 1 minute long alarm is not a solution for me.

like image 633
tiagosilva Avatar asked Dec 14 '15 16:12

tiagosilva


1 Answers

If you need to do something like this often, then wOxxOm is absolutely correct: Event page is a bad approach for your needs.

Documentation should not be misinterpreted: persistent background pages are not in any way deprecated. Event pages are a more efficient solution for background pages that process things irregularly and/or rarely.

Frequent timers do not fall into this category. After all, "spinning up" the Event page frequently is a considerable resource/performance loss as opposed to keeping it ready at all times.


Now, the question becomes more tricky when you only need to do this timeout as a part of infrequent, as opposed to regular, action, when you think that long pauses between those actions can benefit from Event page model. This can happen!

The goal then becomes to appear "busy" enough to Chrome so that the Event page shutdown does not happen.

Probably the easiest way is to just invoke the timer a bit more frequently, as the Event page is guaranteed to persist for a couple of seconds:

var SAFE_DELAY = 1000; // Guaranteed not to fall asleep in this interval

function setBusyTimeout(callback, delay) {
  if(delay <= SAFE_DELAY) {
    setTimeout(callback, delay);
  } else {
    var start = Date.now(); // setTimeout drifts, this prevents accumulation
    setTimeout(
      function() {
        setBusyTimeout(callback, delay - (Date.now() - start));
      }, SAFE_DELAY
    );
  }
  // Can be expanded to be cancellable by maintaining a mapping
  //   of "busy timeout IDs" to real timeoutIds
}

It's a sort of a very "sparse" busy-wait, that should not consume much resources - again, if used infrequently.

Other soultions may include maintaining an open port through chrome.runtime.connect and friends. I doubt it's more CPU-efficient than the above.

like image 190
Xan Avatar answered Sep 22 '22 13:09

Xan