How to prevent/detect race condition between processing and restoring store data when waking up an Event page

牧云@^-^@ 提交于 2019-12-14 01:15:12

问题


I am using sendMessage and onMessage listener (both in background and content pages), and I am seeing some messages are getting lost. I have a few "global" variables that I store everytime I go to suspend state, and restore them among the first things when the script starts (I register the handlers first). However, given that the chrome.storage is asynchronous, I suspect message processing is happening before I get to load the global state (and hence the appearance of losing the messages).

Following is the relevant piece of code.

# 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 onAlarm only continues processing if the global variables have been reloaded?

I use chrome.storage.local.set/get which are asynchronous.

Original question to get debugging hints about suspended/wake states here...

How to debug background/event page suspended state


回答1:


Well, you can't do anything about async nature of Event page processing and Chrome Storage API. And there's no "delaying until" in async JS.

Therefore, you'll need to make do with 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();


来源:https://stackoverflow.com/questions/31416248/how-to-prevent-detect-race-condition-between-processing-and-restoring-store-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!