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

Chrome扩展报错:Receiving end does not exist,求排查方案

解决Chrome扩展偶发的「Could not establish connection. Receiving end does not exist」报错

这个偶发的连接问题我之前也碰到过,核心原因是popup发送消息时,目标标签页的content script还没加载完成,或者页面状态不稳定导致接收端暂时不可用。结合你的代码,我给你几个针对性的解决方案:

1. 捕获消息发送时的错误,避免报错阻塞

chrome.tabs.sendMessage在接收端不存在时会触发runtime.lastError,但你的代码里没处理这个错误,导致控制台抛出异常。我们可以在回调里捕获这个错误,甚至加个重试逻辑:

修改你的sendRequest函数:

function getSelectedTab() {
  // 注意:chrome.tabs.getSelected已经被废弃,推荐用chrome.tabs.query替代
  return new Promise(function(resolve, reject) {
    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
      tabs.length ? resolve(tabs[0]) : reject(new Error("找不到激活的标签页"));
    });
  });
}

function sendRequest(data) {
  data = data || { action: undefined };
  return new Promise(function(resolve, reject) {
    getSelectedTab().then(function(tab) {
      chrome.tabs.sendMessage(tab.id, data, function(response) {
        // 捕获接收端不存在的错误
        if (chrome.runtime.lastError) {
          console.warn("接收端暂不可用,尝试重试:", chrome.runtime.lastError.message);
          // 延迟300ms后重试一次
          setTimeout(() => {
            chrome.tabs.sendMessage(tab.id, data, function(retryRes) {
              chrome.runtime.lastError ? reject(chrome.runtime.lastError) : resolve(retryRes);
            });
          }, 300);
          return;
        }
        resolve(response);
      });
    }).catch(reject);
  });
}

2. 规范Content Script的消息监听逻辑

你的监听代码里存在两个小问题:一是分支逻辑有遗漏(比如"this"分支没有调用sendResponse),二是如果有异步操作的话没保持连接。Chrome要求每个消息都必须调用sendResponse,否则会认为连接未正常关闭,可能引发异常:

修改content.js的监听:

chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
  switch(request.action) {
    case "this":
      console.log({ dom: doThis() });
      sendResponse({}); // 即使不需要返回数据,也要调用sendResponse
      break;
    case "that":
      // 如果doThat是异步函数,要return true保持连接直到sendResponse被调用
      // 示例:
      // doThat().then(result => sendResponse({ dom: result }));
      // return true;
      sendResponse({ dom: doThat() });
      break;
    case "other":
      doOther();
      sendResponse({}); // 同样要调用sendResponse
      break;
    default:
      sendResponse({});
  }
});

3. 确保Content Script已加载完成

有时候标签页刚刷新、切换或者还没加载完,content script还没注入成功。我们可以先检查页面状态,甚至主动注入content script:

升级sendRequest函数,加入页面状态检查和主动注入逻辑:

function sendRequest(data) {
  data = data || { action: undefined };
  return new Promise(function(resolve, reject) {
    getSelectedTab().then(function(tab) {
      // 先检查页面是否加载完成
      if (tab.status !== "complete") {
        console.warn("页面未加载完成,延迟后重试");
        setTimeout(() => sendRequest(data).then(resolve).catch(reject), 500);
        return;
      }

      chrome.tabs.sendMessage(tab.id, data, function(response) {
        if (chrome.runtime.lastError) {
          // 尝试主动注入content script(需要activeTab权限,你的manifest已经声明了)
          chrome.tabs.executeScript(tab.id, {file: "content.js"}, function() {
            if (chrome.runtime.lastError) {
              reject(new Error("注入content script失败:" + chrome.runtime.lastError.message));
              return;
            }
            // 注入成功后再次发送消息
            chrome.tabs.sendMessage(tab.id, data, resolve);
          });
          return;
        }
        resolve(response);
      });
    }).catch(reject);
  });
}

总结

这个偶发报错本质是popup和content script的生命周期不同步:popup打开时,目标页面的content script可能还没准备好。通过错误捕获、重试机制、规范消息响应逻辑,以及主动确保content script加载,基本可以解决这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:34:49