Chrome扩展报错:‘消息端口在收到响应前已关闭’的解决方法
解决Chrome扩展中“The message port closed before a response was received”错误
问题背景
我在开发Chrome扩展时,通过chrome.runtime.sendMessage从内容脚本向后台脚本传递参数发起POST请求,后台脚本处理完请求后想用sendResponse向内容脚本返回结果,但始终触发“The message port closed before a response was received”错误。
原后台脚本代码
chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => { let res = await fetch(message.endpoint, { 'method': 'POST', 'headers': message.headers, 'body': message.body }) let json = await res.json(); console.log('json data:' + json); sendResponse({ 'status': true, 'url': json.url }); });
原内容脚本代码
chrome.runtime.sendMessage({ endpoint: 'https://example.com/api', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ key: 'value' }) }, (response) => { console.log(response); });
我已经尝试在chrome.runtime.onMessage监听器末尾添加return true,但问题仍未解决。
解决方案
通过调整消息传递方式解决了该问题,具体修改如下:
修改后的内容脚本
// 向后台脚本发送请求 chrome.runtime.sendMessage({ endpoint: 'https://example.com/api', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ key: 'value' }) }, (response) => { console.log(response); }); // 监听来自后台脚本的响应消息 chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.message === "audio_url") { console.log('audio_url:' + request.audio_url); sendResponse({ 'status': true, }); } });
修改后的后台脚本
// 监听内容脚本的请求 chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => { // 先返回一个空响应关闭初始消息端口 sendResponse({ 'status': true }); // 处理POST请求 let res = await fetch(message.endpoint, { 'method': 'POST', 'headers': message.headers, 'body': message.body }); let json = await res.json(); console.log('json data:' + json); console.log('url:' + json.url); // 确保能获取到当前tab的ID if (sender.tab === undefined || sender.tab.id === undefined) return; // 通过chrome.tabs.sendMessage向内容脚本发送处理结果 chrome.tabs.sendMessage(sender.tab.id, { message: "audio_url", audio_url: json.url }, function (response) { console.log(`status:`, response.status); }); return true; });
问题原因分析
原方案中直接用sendResponse返回异步处理结果会导致消息端口提前关闭,因为sendResponse在异步操作完成前就失去了有效上下文。另外,runtime.sendMessage的响应机制不适合传递异步处理后的结果到内容脚本,改用chrome.tabs.sendMessage可以直接从后台脚本主动向内容脚本发送消息,绕过原有的消息端口限制,避免端口关闭错误。
内容的提问来源于stack exchange,提问作者Nori
相关产品推荐
相关产品推荐

