'Emulate setTimeout with setInterval not working for nested

I write extension for Chrome. And I need run delayed tasks when background page inactive. Cause setTimeout not working in background tabs, I try emulate setTimeout with setInterval, like code below (located in content script):

window.timings = [];

function set_timeout(func, time){
  var now = new Date() / 1;
  window.timings.push({
    func: func,
    time: time + now
  });
}

function tick(){
  var now = new Date() / 1;
  window.timings = window.timings.filter(function(delay_obj){
    if (now > delay_obj.time){
      delay_obj.func.call();
      return false;
    } else {
      return true;
    }
  });
}

$(function() {
  setInterval(tick, 1000);
  // some code
});

And it don't work when set_interval call in delay function:

set_timeout(function(){
  console.log('func1');
}, 2000);

set_timeout(function(){
  console.log('func2');

  set_timeout(function(){
    console.log('func3');
  }, 3000);

}, 3000);

Output:

func1
func2

Why func3 not displayed?



Solution 1:[1]

You're apparently using an event page declared with "persistent": false in manifest.json, it is unloaded after 15 seconds of inactivity. The linked documentation says to use chrome.alarms API.

  • For a delay less than 15 seconds since the last chrome event:

    Use setTimeout or setInterval.

  • For a delay of 15-60 seconds since the last chrome event:

    Don't use the event page, switch to "persistent": true in manifest.json.

  • For a delay of 60 seconds or more:

    manifest.json:

      "permissions": ["alarms"],
    

    background script:

      chrome.alarms.create("MyInterval1", {when: Date.now() + 1 * 60e3});
    
      chrome.alarms.onAlarm.addListener(function(alarm) {
          if (alarm.name == "MyInterval1") {
              console.log("Yay!");
              chrome.alarms.create("MyInterval1", {when: Date.now() + 1 * 60e3});
          }
      });
    

    Also note:

    Other asynchronous HTML5 APIs like notifications and geolocation will not complete if the event page shuts down. Instead, use equivalent extension APIs, like notifications.

    If your extension uses, extension.getBackgroundPage, switch to runtime.getBackgroundPage instead. The newer method is asynchronous so that it can start the event page if necessary before returning it.

Note that in a published extension the interval between the next alarm and the last fired alarm is at least 1 minute even if you specify a smaller value like 15 seconds (15*1000).

Source: https://developer.chrome.com/docs/extensions/reference/alarms/#method-create

In order to reduce the load on the user's machine, Chrome limits alarms to at most once every 1 minute but may delay them an arbitrary amount more. That is, setting delayInMinutes or periodInMinutes to less than 1 will not be honored and will cause a warning. 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.

To help you debug your app or extension, when you've loaded it unpacked, there's no limit to how often the alarm can fire.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1