关于chrome.tabs.sendMessage及Promise使用的技术问题咨询
问题根因
- 内容脚本的
chrome.runtime.onMessage监听函数处理异步逻辑时,没有显式返回true:Chrome扩展的消息通信机制中,如果监听函数内需要异步执行后再调用sendResponse,必须返回true告知浏览器保留sendResponse通道,否则浏览器会判定监听函数无返回值,直接触发sendMessage的回调,回调参数为undefined。 - 内容脚本未成功注入当前页面:如果当前活跃标签页没有加载匹配的内容脚本、或内容脚本未注册消息监听逻辑,Chrome会直接触发
sendMessage回调,无返回值。 - 回调与Promise写法混用:Manifest V3版本的
chrome.tabs.sendMessage原生支持Promise返回,如果同时传入回调函数又使用await,会导致逻辑执行顺序混乱。
修复方案
1. 修正内容脚本的消息监听逻辑
在异步处理逻辑结束后调用sendResponse,末尾显式返回true:
// 内容脚本代码 chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { if (msg.action === "getDOM") { // 你的异步处理逻辑,比如DOM遍历、接口请求等 const result = { incident: [/* 处理后的数据 */] } // 异步场景下(存在await、setTimeout等异步操作)必须调用sendResponse返回结果 sendResponse(result) // 关键:返回true告知浏览器等待异步响应,不要销毁通信通道 return true } })
2. 修正Popup代码逻辑
移除回调写法,直接使用await调用chrome.tabs.sendMessage,用try/catch捕获异常:
document.addEventListener('DOMContentLoaded', async function() { console.log('got tabs id'); const tab = await getCurrentTab(); console.log('Active tab ' + tab.id); console.log('Sending Message to Content'); try { // 直接await sendMessage的返回值,无需传入回调 const ret = await chrome.tabs.sendMessage(tab.id, {action: "getDOM"}); console.log('Receiving Message from Content'); if (!ret?.incident?.length) return; globalThis.response = ret; processResponse(response); } catch(err) { // 可打印chrome.runtime.lastError查看具体错误原因 console.log('doing nothing, bad return data', err) window.close(); return; } return; });
3. 排查验证路径
- 在内容脚本的监听函数第一行打印日志,确认消息已成功送达内容脚本
- 检查Manifest配置中内容脚本的匹配规则,确认当前活跃页面符合匹配规则,内容脚本已成功注入
内容的提问来源于stack exchange,提问作者Luigi
相关产品推荐
相关产品推荐

