Chrome扩展中Background.js向Content.js发送数组失败问题
问题分析与修复方案
你遇到的「Could not establish connection. Receiving end does not exist」错误,核心原因是发送消息时目标标签页的content.js未加载,或者代码逻辑存在绑定/异步问题,以下是具体修复步骤:
一、核心问题拆解
- content.js加载时机问题:如果当前激活标签页没有匹配content.js的注入规则(比如manifest里的matches配置不对),或者页面还没加载完成就发送消息,会导致接收端不存在。
- background.js逻辑错误:把按钮点击监听嵌套在
chrome.runtime.onMessage回调里,会导致每次收到content.js的消息就重复绑定点击事件,逻辑混乱;同时异步操作(比如IndexedDB)里的消息发送没有正确处理上下文。 - 端口通信未配对:使用
port.postMessage时,content.js没有注册chrome.runtime.onConnect监听器,无法建立连接。
二、修复后的代码示例
1. content.js 修正版
function clickPlanet() { const myDataArray = []; // 此处处理并填充myDataArray // 向background.js发送数据 chrome.runtime.sendMessage({ myDataArray }, (response) => { if (chrome.runtime.lastError) { console.error(chrome.runtime.lastError); return; } // 可在此处理background的同步响应(如果需要) }); } clickPlanet(); // 监听来自background.js的消息 chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.indexArray) { console.log("Received indexArray in content.js:", message.indexArray); // 可选:给background返回响应 sendResponse({ status: "received" }); } else if (message.greeting) { console.log("Received greeting:", message.greeting); sendResponse({ reply: "Hi from content!" }); } else { console.log("Unknown message:", message); } // 若需异步处理响应,返回true // return true; }); // 若使用端口通信,添加以下监听 chrome.runtime.onConnect.addListener((port) => { if (port.name === "content-script") { port.onMessage.addListener((msg) => { console.log("Port message received:", msg); port.postMessage({ reply: "Port connected!" }); }); } });
2. background.js 修正版
// 全局绑定按钮点击事件,不要嵌套在onMessage回调内 document.getElementById('send-button').addEventListener('click', () => { chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { if (!tabs[0]) return; // 发送消息并处理错误 chrome.tabs.sendMessage(tabs[0].id, { greeting: "hello" }, (response) => { if (chrome.runtime.lastError) { console.error("发送失败:", chrome.runtime.lastError.message); return; } console.log("Response from content.js:", response); }); // 端口通信:需确保content.js已注册onConnect监听 const port = chrome.runtime.connect({ name: "content-script" }); port.onMessage.addListener((msg) => { console.log("Port reply:", msg); }); port.postMessage({ greeting: "Hello from background!" }); }); }); document.getElementById('checkk-button').addEventListener('click', () => { // 从全局变量获取content.js之前发送的数据 if (!window.storedMyDataArray) { console.log("未收到content.js的数据"); return; } const data = window.storedMyDataArray; let db; const request = indexedDB.open("OurDatabase4", 1); request.onsuccess = (event) => { db = event.target.result; // 此处处理IndexedDB逻辑,填充indexArray const indexArray = []; // 发送indexArray到当前激活标签页 chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { if (!tabs[0]) return; chrome.tabs.sendMessage(tabs[0].id, { indexArray }, (response) => { if (chrome.runtime.lastError) { console.error("发送indexArray失败:", chrome.runtime.lastError.message); return; } console.log("Response from content.js:", response); }); }); }; request.onerror = (event) => { console.error("IndexedDB打开失败:", event.target.error); }; }); // 监听content.js的消息,存储数据到全局变量 chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.myDataArray) { window.storedMyDataArray = message.myDataArray; // 若需同步返回响应 sendResponse({ status: "data received" }); } // 若为异步处理,返回true // return true; });
三、额外注意事项
- manifest配置检查:确保content.js的
matches规则包含你要操作的网站,示例:"content_scripts": [ { "matches": ["https://your-target-site.com/*"], "js": ["content.js"], "run_at": "document_idle" } ] - 页面加载时机:添加
"run_at": "document_idle"可确保content.js在页面加载完成后注入。 - 错误处理:所有
sendMessage调用都要处理chrome.runtime.lastError,避免控制台报错。
内容的提问来源于stack exchange,提问作者Nagatski
相关产品推荐
相关产品推荐

