Chrome扩展后台脚本传入的回调为何静默失败或返回false?
Chrome扩展跨域消息回调异常问题(Manifest V2)
问题背景
正在重构一款运行多年的Chrome扩展,将内容脚本中的chrome.runtime.*调用迁移至扩展后台脚本,使脚本可在外部域名运行(而非仅在扩展内的内容脚本中)。使用Manifest V2,externally connectable配置无误。
具体问题:网页端脚本向扩展发送消息并携带结果回调,扩展后台监听器可接收包含正确数据的消息,回调为正常函数对象——用测试数据调用时可正常工作,但其他场景下回调完全无反应。
代码示例
以下示例用Python(Brython)编写,纯JavaScript环境下问题一致,以console.log作为测试回调:
# ===== 客户端脚本 chrome.runtime.sendMessage(EXTN_ID, {'action': 'get_tabs', 'args': {}}, console.log) # ===== 服务端(扩展后台脚本) def get_tabs(args, sender, callback): args['windowId'] = sender.tab.windowId # 获取调用者窗口的标签页 callback('foo') # <--- 正常:客户端控制台打印foo chrome.tabs.query(args, callback) # <-- 通常无反应:客户端控制台无输出,后台控制台无错误,偶尔客户端打印"false" # --- 另一种尝试方式 def check_result(res): console.log(res) # <-- 正常:扩展后台控制台打印标签页信息 callback(res) # <-- 无反应:客户端控制台无输出,两个控制台均无错误 chrome.tabs.query(args, check_result) # <-- 触发check_result,后台打印正确结果,但客户端无响应 # ---------------- # 消息监听器(工作正常) def receive(msg, sender, callback): if msg.action == 'get_tabs': get_tabs(msg.args, sender, callback) return True # <-- 支持异步响应 chrome.runtime.onMessageExternal.addListener(receive)
观测到的行为
- 将回调直接传入
chrome.tabs.query无任何反应,静默失败 - 在调用
chrome.tabs.query前,手动调用回调可正常返回测试数据 - 用包装函数包裹客户端回调时,
chrome.tabs.query能拿到正确结果,但传递给原回调时静默失败 - 一旦调用
chrome.tabs.query,客户端通常看不到回调触发,偶尔会收到false值——即便包装函数拿到正确结果,客户端回调仍会传入false而非真实数据
已尝试的修复方案
- 将Python回调包装为JavaScript函数,无改善(已确认纯JS环境问题一致)
- 移除函数签名中的
*args和**kwargs,怀疑Brython破坏回调参数,无效果 - 尝试客户端存储回调、发送回调ID给扩展的方案:
- 客户端存储回调,向扩展发送回调ID
- 扩展创建本地回调获取
chrome.tabs.query结果 - 本地回调向客户端发送包含结果和回调ID的新消息
- 客户端根据ID调用存储的回调
但此方案无法落地:Chrome仅允许客户端主动发起消息,扩展无法主动向客户端发送消息;也无法用window.postMessage联系客户端监听器;虽可用chrome.runtime.connect建立长连接,但单次往返用长连接过于冗余,长期运行网页管理连接成本高
内容的提问来源于stack exchange,提问作者Ed_
相关产品推荐
相关产品推荐

