为何检查runtime.lastError会触发Chrome扩展的端口错误?
sendMessage带回调时的端口关闭错误 我之前也碰到过这个诡异的问题,折腾了好一阵才搞明白根源!咱们一步步拆解:
问题原因
当你给chrome.runtime.sendMessage加上回调函数时,Chrome的消息机制会默认认为你需要后台脚本给一个响应——它会建立一个临时的消息端口,等待后台通过sendResponse方法完成这次交互。
如果你的后台监听器既没调用sendResponse,也没在同步执行阶段返回true(表示要异步回复),那么监听器执行完之后,Chrome会立刻关闭这个端口。这时候前端的回调就会触发lastError,也就是你看到的The message port closed before a response was received错误。
你提到的返回true只是延迟错误,也很好解释:返回true是告诉Chrome“我稍后会异步调用sendResponse,先别关端口”,但如果你最终根本没调用sendResponse,Chrome过一会儿还是会强制关闭端口,错误依然会出现。
解决方案
因为你明确说这是单向消息,不需要后台返回响应,所以有两种靠谱的处理方式:
1. 直接使用无回调的sendMessage(推荐)
就像你已经测试的那样,去掉回调函数:
// options.js 无报错版本,完美适配单向消息场景 chrome.runtime.sendMessage({ hello: true });
这种情况下,Chrome不会建立需要响应的端口,自然不会触发任何错误,完全符合你的需求。
2. 如果必须用回调(比如要做发送确认)
那就在后台监听器里主动调用sendResponse,哪怕只是传个空值,告诉Chrome“我收到消息了,这次交互结束”:
修改你的background.js:
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { if (typeof request.hello !== "undefined") { console.log("I got it!"); sendResponse(); // 主动完成消息交互,避免端口报错 } });
这样前端带回调的调用就不会再报错了,因为Chrome收到了明确的响应信号,端口会正常关闭。
额外提醒
别用return true来应付这个问题,除非你真的有异步回复的需求(比如要等某个API请求完成再回复)。如果只是单向消息,要么用无回调的调用,要么主动调用sendResponse,这才是规范的做法。
内容的提问来源于stack exchange,提问作者Gaurang Tandon




