How to prevent / detect race condition between processing and restoring storage data when waking up the "Event" page

I use sendMessage

and onMessage

the listener (as in the background, and on content pages), and I see that some messages are lost. I have a few "global" variables that I save each time I go to suspend state, and restore them among the first things when I run the script (register the handlers first). However, given which chrome.storage

is asynchronous, I suspect that message processing is happening before I get the global state loaded (and hence the occurrence of lost messages).

Below is the relevant code snippet.

# Register some important listeners.
chrome.alarms.onAlarm.addListener(onAlarm);
chrome.runtime.onMessage.addListener(onMessage);

# Define global variables.
var tabIdList = new Array();
var keepAlives = new Array();
keepAlives["myTab1"] = -1;
keepAlives["myTab2"] = -1;
tabIdList["myTab1"] = -1;
tabIdList["myTab2"] = -1;

# Reload previously stored state of global variables...
reloadGlobalVariable();


# Handle received messages, anytime a message is received,
# set keepAlive for the tab that sends the message.
#
function onMessage(msg, sender) {
  if (sender.tab) {
    if (msg.message === "hello") {
        recordNewTab(msg.tabName, sender.tab.id);
    } 
  keepAlive(msg.tabName, sender.tab.id);
}

function recordNewTab(tabName, tabId) {
    tabIdList[tabName] = tabId;
}

function keepAlive(tabName, tabId) {
    if (tabIdList[tabName] == tabId) {
        keepAlives[tabName] = 1;
    }
}


chrome.runtime.onSuspend.addListener(function() {
    storeGlobalState();
});


function onAlarm(alarm) {
    for (var key in tabIdList) {
      if (tabIdList[key] != -1) {
        if (keepAlives[key] == -2) {
           removeTabRecord(key);
        } else {
          --keepAlives[key];
          sendMessage(key, "ping"); // content pages respond to this message
        }
      }
    }
  storeGlobalState(); // probably unnecessary.
}

      

How can I make sure that it onAlarm

only keeps processing if globals are reloaded?

I am using chrome.storage.local.set

/ get

which are asynchronous.

Original question to get debug hints on suspended / awake states here ...

How to debug suspended state of background / events page

+3


source to share


1 answer


Well, there is nothing you can do about the asynchronous nature of the event page handling and Chrome storage API. And there is no "delay before" in async JS.

Hence, you will need to make callbacks. This should work:



var globalsReady = false;

chrome.foo.onBar.addListener(handler);

function handler(a, b, c) {
  restoreGlobals(function() {
    /* Do actual handling using a, b, c */
  });
  // Special note for onMessage: if you are sending a reply asynchronously,
  //  you'll need to return true; here
}

function restoreGlobals(callback) {
  if(!globalsReady) {
    chrome.storage.local.get(/*...*/, function(data) {
      /* restore globals here */
      globalsReady = true;
      if(typeof callback == "function") callback();
    });        
  } else {
    // Already done restoring
    if(typeof callback == "function") callback();
  }
}

restoreGlobals();

      

+3


source







All Articles