Chrome扩展报错:消息端口未收到响应即关闭,求通信及监听器解决方案
Fixing Chrome Extension Message Port Error & Web Request Listener Removal
Let's break down your issues and fix them step by step:
1. Root Cause of the Errors
Your problems stem from two critical mismatches in your code:
- Incorrect message response flow: You’re sending a new message from the content script with
chrome.runtime.sendMessage(), but the background script is waiting for a response via the built-insendResponsecallback fromchrome.tabs.sendMessage(). This disconnect causes the message port to close before the background gets the expected response, triggering the runtime error. - Failed listener removal: You added an anonymous function to
chrome.webRequest.onCompleted, but tried to removesendURL(a completely separate function). Since listener removal requires an exact function reference, the original listener stays active, triggering repeated message sends and creating an unintended loop.
2. Fixed Code Implementations
Modified contentScript.js
We’ll use the sendResponse parameter to reply directly to the background’s message instead of sending a new one:
const m3u8 = new M3U8(); console.log(m3u8); chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { console.log(message); // Send the "ok" response directly to the background's sendMessage callback sendResponse({ status: 'ok' }); const download = m3u8.start(message.url); download.on("progress", progress => { console.log(progress); }).on("finished", finished => { console.log(finished); }).on("error", error => { console.log(error); }); });
Modified background.js
We’ll use a named function for the web request listener so we can properly reference and remove it later:
// Named function for the web request listener (enables proper removal) function handleWebRequestCompleted(request) { console.log(request); sendURL(request); } const sendURL = (request) => { chrome.tabs.sendMessage(request.tabId, { url: request.url }, (response) => { // Add optional chaining to avoid errors if response is undefined (e.g., tab closed) if (response?.status === 'ok') { // Remove the EXACT listener we added earlier chrome.webRequest.onCompleted.removeListener(handleWebRequestCompleted); console.log("Web request listener removed successfully"); } }); } // Attach the named listener to webRequest.onCompleted chrome.webRequest.onCompleted.addListener( handleWebRequestCompleted, { urls: ["https://*.myurl.net/*/*prog_index.m3u8*"], types: ["xmlhttprequest"] }, ["responseHeaders"] );
3. Key Explanations
- Message Response Fix: The
chrome.tabs.sendMessage()callback relies on the content script using thesendResponsefunction provided in itsonMessagelistener. This ensures the message port stays open just long enough to deliver the response, eliminating the "port closed" error entirely. - Listener Removal Fix: By defining a named function (
handleWebRequestCompleted) and using it for bothaddListenerandremoveListener, we give the browser a clear reference to the listener instance it needs to remove. Anonymous functions can’t be targeted this way because they don’t have a reusable identity.
Bonus: Robustness Upgrade
To avoid edge cases like the target tab being closed before sending the message, add a quick check:
const sendURL = (request) => { chrome.tabs.get(request.tabId, (tab) => { if (chrome.runtime.lastError || !tab) { console.log("Target tab not found, aborting message send"); return; } chrome.tabs.sendMessage(tab.id, { url: request.url }, (response) => { if (response?.status === 'ok') { chrome.webRequest.onCompleted.removeListener(handleWebRequestCompleted); } }); }); }
内容的提问来源于stack exchange,提问作者alfaun0
相关产品推荐
相关产品推荐

