Reputation: 85
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
Upvotes: 3
Views: 370
Reputation: 77551
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();
Upvotes: 3