This is a persistent error I encounter in my Chrome Extension, when I send a message from the background script to the content script.
Weirdly enough, the error happens only under SOME conditions -- for example, if I try to send a message after an onUpdated event listener is triggered, I almost always receive that error. The only workaround I've found is to introduce an arbitrary wait of 3-5 seconds, only after which the message gets reliably sent.
Even weirder I do NOT see the error when the message is sent via an onActivated event listener -- even though basically all the rest of the code is identical aside from the event listener that triggers it.
If I had to guess, it's probably something to do with the fact that the webpage is still loading, the content script for whatever reason isn't available for be receiving messages -- and when you try to send a message to it, it doesn't work.
I tried another workaround where I checked the status of the active tab, and looked for only when the check.status === "complete", but that weirdly didn't work, even when the webpage was clearly loaded. I could loop over it 100 times and it would just say it's in a persistent state of loading.
Has anyone found a reliable method to actually prevent this error from occurring in their Chrome Extensions?
Pertinent code:
BACKGROUND SCRIPT:
chrome.tabs.onUpdated.addListener(function(tabId, change, tab) {
if (tab.active && change.url) {
UpdatedTabURL = change.url;
UpdatedURLTabID = tabId;
if (typeof PreviousURL !== 'undefined') {
if (UpdatedTabURL.indexOf(PreviousURL) != -1) {
return; // this functionally aborts the rest of the code if they're on the same URL. The timer thus doesn't auto-stop and keeps running.
} // this is specifically to keep the timer running if they're clicking links on and within the same URL website (e.g. browsing around on Reddit)
}
for (let i = 0; i < AllURLsToAvoid.length; i++) {
if (UpdatedTabURL.indexOf(AllURLsToAvoid[i]) != -1) {
PreviousURL = AllURLsToAvoid[i];
chrome.windows.onFocusChanged.addListener(function(windowId) {
if (windowId === chrome.windows.WINDOW_ID_NONE) { // If the user minimized the current browser window, it removes the timer
chrome.tabs.sendMessage(tabId, {greeting: "Remove Timer"}, function() {
})
}
});
chrome.tabs.onActivated.addListener(function(activeInfo) {
if (activeInfo.tabId !== UpdatedURLTabID) { // if the user switches to another tab, it removes the timer
chrome.tabs.sendMessage(UpdatedURLTabID, {greeting: "Remove Timer"}, function() {
})
}
});
setTimeout(function() { // arbitrarily waits 5 seconds. why? because without this, the receiving end doesn't exist. this waits for it to load. a shitty, suboptimal but functional solution.
chrome.tabs.sendMessage(tabId, {greeting: "Start Timer"}, function() {
})
}, 3000);
}
}
}
});
CONTENT SCRIPT:
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
console.log("Message received:", request);
if (request.greeting === "Start Timer") {
sendResponse({farewell: "Timer Started"});
RemoveTimer();
StopTimer();
AddStickyTimer();
RunTimer();
}
if (request.greeting === "Remove Timer") {
sendResponse({farewell: "Timer Removed"});
// alert("TIMER REMOVED");
RemoveTimer();
StopTimer();
}
});