Chrome扩展消息API实现报错及修正后新问题排查
问题分析与修复方案
我来帮你一步步排查并修复这两个Chrome扩展消息API的问题:
第一个错误:Uncaught TypeError: chrome.runtime.onMessage is not a function
错误原因
在你的popup.js中,你直接调用了chrome.runtime.onMessage(...),但**chrome.runtime.onMessage是一个事件对象,不是可直接执行的函数**。要注册消息监听器,必须使用它的.addListener()方法。
修复代码(popup.js)
把原来的消息监听代码:
chrome.runtime.onMessage(function(message, sender, response){ console.log(sender); if( message.type == 'feed_data' ){ console.log(message.data); } });
改成:
chrome.runtime.onMessage.addListener(function(message, sender, response){ console.log(sender); if( message.type == 'feed_data' ){ console.log(message.data); } });
第二个错误:TypeError: Error in invocation of tabs.sendMessage(...):No matching signature
这个错误是由多个小问题叠加导致的,逐一拆解:
错误原因1:标签页ID(tabId)未正确获取
你修改后的background.js里监听了extension_started消息来获取id,但你的代码里没有任何地方发送这个消息,导致id始终是undefined。调用chrome.tabs.sendMessage时,第一个参数必须是有效的标签页ID,传入undefined就会触发签名不匹配的错误。
错误原因2:消息类型不匹配
background.js里发送的消息类型是grab_stories,但你的内容脚本main.js里监听的是grab_feed,两者不一致,导致内容脚本无法响应消息。
错误原因3:内容脚本响应方式错误
你在内容脚本里用了sendResponse({...}),但Chrome消息API的监听器中,第三个参数的名字是response(你自己定义的参数名),正确的响应方式是调用这个response()函数,而不是sendResponse。
修复代码(background.js)
我们直接在收到init_popup_feed消息时,获取当前活跃的标签页ID(假设内容脚本注入到当前活跃页),然后发送正确的消息类型:
chrome.runtime.onMessage.addListener(function(message, sender, response){ console.log(message.type); if( message.type == 'init_popup_feed' ){ // 获取当前活跃的标签页 chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { const activeTabId = tabs[0].id; // 发送与内容脚本匹配的消息类型grab_feed chrome.tabs.sendMessage(activeTabId, {type:'grab_feed'}, function(response){ console.log(response); // 把数据转发给popup chrome.runtime.sendMessage({type:'feed_data', data:response.data}); }); }); } else if( message.type == 's_feed'){ chrome.runtime.sendMessage({type:'feed_data', data:message.data}); } });
修复代码(main.js - 内容脚本)
修正响应函数的调用方式:
(function($){ $(document).ready(function(){ console.log('Extension Started!'); const l = []; var d; chrome.runtime.onMessage.addListener(function(message, sender, response){ console.log(message.type); if( message.type == 'grab_feed' ){ // ... 你的数据抓取代码 ... // 用response()发送响应,而不是sendResponse response({type:'s_feed', data:l}); console.log(l); // 如果你的数据抓取是异步操作(比如AJAX),需要返回true来保持消息通道开放 // return true; } }); }); }(jQuery));
完整修正后的代码汇总
popup.js
(function($){ $(document).ready(function(){ console.log('Extension Started!'); chrome.runtime.sendMessage({type:'init_popup_feed'}); // 正确注册消息监听器 chrome.runtime.onMessage.addListener(function(message, sender, response){ console.log(sender); if( message.type == 'feed_data' ){ console.log(message.data); } }); }); }(jQuery));
background.js
chrome.runtime.onMessage.addListener(function(message, sender, response){ console.log(message.type); if( message.type == 'init_popup_feed' ){ // 查询当前活跃标签页 chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { const activeTabId = tabs[0].id; chrome.tabs.sendMessage(activeTabId, {type:'grab_feed'}, function(response){ console.log(response); // 转发数据到popup chrome.runtime.sendMessage({type:'feed_data', data:response.data}); }); }); } else if( message.type == 's_feed'){ chrome.runtime.sendMessage({type:'feed_data', data:message.data}); } });
main.js(内容脚本)
(function($){ $(document).ready(function(){ console.log('Extension Started!'); const l = []; var d; chrome.runtime.onMessage.addListener(function(message, sender, response){ console.log(message.type); if( message.type == 'grab_feed' ){ // ... 你的数据抓取逻辑 ... // 正确发送响应 response({type:'s_feed', data:l}); console.log(l); // 异步操作时取消注释下面一行 // return true; } }); }); }(jQuery));
测试验证
- 确保内容脚本已正确注入到目标页面(可以在页面控制台查看
Extension Started!日志) - 打开popup,查看popup控制台是否收到数据
- 查看background控制台的日志,确认消息传递流程正常
内容的提问来源于stack exchange,提问作者jihuuNI
相关产品推荐
相关产品推荐

