chrome.runtime.onMessage与Port.onMessage的区别及端口监听器未触发问题
为什么你的
port.onMessage.addListener没被触发? 问题出在你混淆了Chrome扩展的两种消息通信机制,而且你的background脚本完全没处理content script发起的长连接请求,自然触发不了port的消息监听。
先理清两种通信方式的区别
chrome.runtime.onMessage/chrome.tabs.sendMessage:这是一次性请求-响应模式,发一次消息,对应一次接收/响应,用完就断。chrome.runtime.connect:这是长连接模式,建立port后可以双向多次收发消息,但要求两端都正确监听连接和消息事件。
你的代码问题所在
你在content script里主动建立了名为knockknock的port连接,但background脚本既没有监听这个连接请求,也没有通过port给content script发消息——反而用了一次性的chrome.tabs.sendMessage,这俩完全是两条互不相关的通信通道,所以port.onMessage.addListener根本没机会触发。
修复方案
第一步:修改background脚本,处理port连接
在backgroundscript.js里添加对port连接的监听,这样才能和content script的port通道互通:
// 监听content script发起的port连接请求 chrome.runtime.onConnect.addListener(function(port) { // 验证连接名称是否匹配 console.assert(port.name === "knockknock"); // 监听来自content script的port消息 port.onMessage.addListener(function(msg) { console.log("background收到port消息:", msg); // 发送消息给content script,触发它的port.onMessage port.postMessage({question: "Who's there?"}); }); }); // 保留你原来的一次性消息(可选,和port无关) chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) { chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) { console.log("一次性消息发送完成"); }); });
第二步:content script代码(可保留,加日志方便调试)
你的content script代码本身没问题,只是可以加日志更清晰:
console.log("content script loaded"); var port = chrome.runtime.connect({name: "knockknock"}); port.postMessage({joke: "Knock knock"}); port.onMessage.addListener(function(msg) { console.log("content script收到port消息:", msg); port.postMessage({answer: "Madame... Bovary"}); }); chrome.runtime.onMessage.addListener(function (msg, sender, response) { console.log("cs:收到一次性消息 ", msg); });
额外注意
- 修改代码后,一定要在Chrome扩展管理页重新加载扩展,确保新脚本生效;
- 检查manifest.json里是否正确配置了background和content script的路径,权限方面这种通信不需要额外特殊权限,只要脚本配置正确即可。
内容的提问来源于stack exchange,提问作者krrishna
相关产品推荐
相关产品推荐

