Chrome MV3与MV2中tabs.onUpdated内sendMessage行为差异排查
问题
我开发了一款Chrome MV3扩展,在background脚本的tabs.onUpdated监听回调中,向新打开的标签页发送消息,content script负责响应该消息。相关代码如下:
background.js
chrome.tabs.onUpdated.addListener(function (tabId, info, tab) { chrome.tabs.sendMessage(tabId, { message:"hellofrombackground" }) });
content-script.js
chrome.runtime.onMessage.addListener(function(e) { if (e.message === "hellofrombackground") console.log(e); })
manifest.json(相关配置)
{ "manifest_version": 3, "permissions": [ "storage", "activeTab", "tabs", ], "background": { "service_worker": "background.js" }, "content_scripts": [ { "matches": [ "<all_urls>" ], "js": [ "content-script.js" ] } ], }
目前出现错误:Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist.,但实际目标标签页已加载content script且能打印来自background的消息。而在MV2中执行相同操作(仅修改manifest必要配置)则无此错误,请问问题出在哪里?
原因分析
Chrome MV3的tabs.onUpdated事件会在标签页状态变化时多次触发——比如标签页刚创建(还没加载content script)、开始加载、加载完成这些阶段都会触发。而MV3中chrome.tabs.sendMessage返回Promise,当发送消息时如果content script还没注入完成,就会抛出连接失败的错误;即使后续content script加载完成后能收到消息,之前那次失败的调用还是会报错。
MV2中chrome.tabs.sendMessage不返回Promise,即使发送失败也不会抛出未捕获的Promise错误,所以你看不到这个报错,但实际上早期的发送操作也是失败的,只是没暴露出来。
解决方案
- 判断标签页加载状态后再发送消息
在tabs.onUpdated回调中,只有当info.status为"complete"时再发送消息,此时content script已经完成注入:
chrome.tabs.onUpdated.addListener(function (tabId, info, tab) { if (info.status === "complete") { chrome.tabs.sendMessage(tabId, { message:"hellofrombackground" }) .catch(err => console.log("消息发送失败:", err)); // 捕获可能的错误,避免未捕获Promise异常 } });
- 捕获Promise错误
如果必须在更早阶段尝试发送消息,一定要手动捕获Promise的错误,避免控制台出现未捕获异常:
chrome.tabs.onUpdated.addListener(function (tabId, info, tab) { chrome.tabs.sendMessage(tabId, { message:"hellofrombackground" }) .catch(err => { // 可以忽略此错误,或者做其他处理 console.log("暂时无法发送消息,content script可能未加载:", err); }); });
内容的提问来源于stack exchange,提问作者Kritidipto Ghosh
相关产品推荐
相关产品推荐

