Chrome扩展新标签页首次加载时内容脚本无法接收后台消息
Chrome扩展新标签页跳转时内容脚本收不到消息的问题解决
问题本质
在新标签页输入URL跳转时,内容脚本加载后立即发送初始化消息,但此时Chrome的sender.tab信息仍停留在chrome://newtab/(tab URL存在更新延迟)。后台基于这个旧的tab信息发送CHANGE_BG消息时,消息会被投递到已处于卸载状态的newtab页面,而非当前加载的目标页面,导致内容脚本无法接收。
解决方案
方案1:后台监听页面加载完成后再发消息
后台不直接在收到内容脚本消息后回发,而是先记录待处理的tab,等页面加载完成且URL匹配后再发送消息:
// background script const pendingTabs = new Set(); chrome.runtime.onMessage.addListener((message, sender) => { if (message.action === "NOTIFY_CONTENT_SCRIPT_LOADED") { console.log(`### ACK content script in page: ${message.pageURL} and tab: ${sender.tab.url}`); // 记录tab和目标URL pendingTabs.add({ tabId: sender.tab.id, targetUrl: message.pageURL }); } }); chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { // 仅处理已加载完成且匹配目标URL的tab if (changeInfo.status === 'complete' && tab.url) { const pendingItem = Array.from(pendingTabs).find(item => item.tabId === tabId && item.targetUrl === tab.url); if (pendingItem) { chrome.tabs.sendMessage(tabId, { action: "CHANGE_BG" }, () => { console.log("### ACK changed BG color of client page"); pendingTabs.delete(pendingItem); }); } } });
方案2:内容脚本等待页面加载完成后再发初始化消息
延迟发送消息,确保tab的URL已更新,后台能拿到正确的tab信息:
// content script chrome.runtime.onMessage.addListener((message, _, sendResponse) => { if (message.action === "CHANGE_BG") { document.body.style.background = "yellow"; sendResponse(); } }); // 等待页面完全加载后发送初始化消息 window.addEventListener('load', () => { console.log("### Notifying background from page: " + location.href); chrome.runtime.sendMessage({ action: "NOTIFY_CONTENT_SCRIPT_LOADED", pageURL: location.href }); });
方案3:后台查询最新tab信息再发消息
收到内容脚本消息后,先获取该tab的最新状态,确认URL匹配后再发送消息:
// background script chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.action === "NOTIFY_CONTENT_SCRIPT_LOADED") { console.log(`### ACK content script in page: ${message.pageURL} and tab: ${sender.tab.url}`); // 查询tab最新信息 chrome.tabs.get(sender.tab.id, (tab) => { if (tab.url === message.pageURL) { chrome.tabs.sendMessage(sender.tab.id, { action: "CHANGE_BG" }, () => { console.log("### ACK changed BG color of client page"); }); } }); sendResponse(); // 必须调用避免内存泄漏 } });
关于chrome.runtime.connect断开的补充
页面跳转时,旧newtab页面的内容脚本被销毁,对应端口会断开。新页面的内容脚本会重新建立连接,后台可以在onConnect事件中记录tab的最新状态,或等待页面加载完成后再通过端口通信。
内容的提问来源于stack exchange,提问作者Vaibhav Nigam
相关产品推荐
相关产品推荐

