You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome扩展popup与content-script通信报错:消息端口提前关闭

问题分析与修复方案

错误原因

这个报错的核心原因是:你给chrome.runtime.onMessage的回调加了async关键字,导致回调变成了异步函数。Chrome的消息传递机制有个规则:

  • 如果回调是同步执行的,会等待你调用sendResponse后再关闭消息端口;
  • 但如果是异步函数(用了async/await),Chrome会默认在函数返回Promise后立刻关闭端口,而你的await chrome.storage.local.get还没执行完,端口就已经关闭,popup那边自然收到「消息端口在收到响应前关闭」的错误。

你之前尝试加return true或sendResponse无效,大概率是位置不对——return true必须在同步阶段返回,用来告诉Chrome要等待异步的sendResponse调用,而不是放在await之后的异步代码里。

修复方法

方法一:同步返回true + 异步完成后调用sendResponse

修改content-script.js:

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  console.log(request);
  if(request.go) {
    // 用立即执行异步函数包裹逻辑,避免把整个回调变成async
    (async () => {
      const go = await chrome.storage.local.get('something');
      console.log(go);
      // 异步操作完成后调用sendResponse返回结果
      sendResponse({status: 'success', data: go});
    })();
    // 必须在同步阶段返回true,告诉Chrome等待异步的sendResponse
    return true;
  }
});

同时优化popup.js为Promise风格调用(更适配async/await):

document.getElementById('go').addEventListener('click', async () => {
  let [tab] = await chrome.tabs.query({active: true, currentWindow: true});
  try {
    const response = await chrome.tabs.sendMessage(tab.id, {go: true});
    console.log('通信成功', response);
  } catch (err) {
    console.log('通信失败', err);
  }
});

方法二:直接使用异步回调(Chrome 88+支持)

如果你的目标Chrome版本在88及以上,可以直接把onMessage的回调写成async函数,此时不需要return true,只需确保回调返回的Promise最终resolve一个值:

chrome.runtime.onMessage.addListener(async (request, sender) => {
  console.log(request);
  if(request.go) {
    const go = await chrome.storage.local.get('something');
    console.log(go);
    // 返回响应数据,Promise会自动resolve这个值
    return {status: 'success', data: go};
  }
});

popup.js同样用上面的Promise风格调用即可。

内容的提问来源于stack exchange,提问作者kodfire

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 20:20:17