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 ...
source to share
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();
source to share