Chrome扩展popup与content script消息通信返回undefined是什么原因?
Chrome扩展消息通信问题修复方案
问题根因
- 消息发送API误用
browser.runtime.sendMessage仅用于扩展内部上下文(popup、后台脚本/Service Worker)之间的通信,无法发送到页面注入的content script,导致content脚本没有收到消息,自然没有合法返回值,最终response为undefined。 - 响应值读取错误
就算通信正常,content script返回的是{test: "foo"}对象,直接将整个对象写入DOM会得到[object Object],需要读取对应属性才能拿到目标字符串。 - 响应通道提前销毁
部分浏览器的扩展API会在onMessage监听器同步执行完成后直接销毁sendResponse通道,就算是同步返回响应也建议添加返回值保持通道可用。 - 兼容问题
Chrome原生扩展API前缀为chrome,如果没有引入webextension-polyfill兼容层,使用browser前缀会导致API调用直接失败。
修复代码
popup.js
// 未加polyfill的Chrome环境请将所有browser替换为chrome // 先查询当前激活的标签页,再向该标签页的content script发消息 browser.tabs.query({active: true, currentWindow: true}, (tabs) => { const activeTab = tabs[0]; browser.tabs.sendMessage(activeTab.id, { test: "foo2" }) .then((response) => { console.log(response); // 读取返回对象的test属性 document.getElementById("testp").innerHTML = response.test; }); });
content.js
browser.runtime.onMessage.addListener((request, sender, sendResponse) => { sendResponse({test: "foo"}); // return true保持sendResponse通道不被提前销毁 return true; });
额外配置要求
需要在manifest.json中添加tabs权限,否则popup无法获取当前标签页ID:
"permissions": ["tabs"]
如果使用Manifest V3,还需要配置对应站点的host权限,匹配content script的注入站点范围。
内容的提问来源于stack exchange,提问作者Doug Smith
相关产品推荐
相关产品推荐

