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

Chrome扩展中为何无法在chrome.tabs.onUpdated监听器内调用chrome.runtime.sendMessage?

解决Chrome扩展错误:Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist. 及URL变更消息的替代实现

错误原因分析

你遇到的错误核心是发送消息时无对应接收端,具体问题出在这几点:

  1. worker.js调用chrome.runtime.sendMessage发送消息,但offscreen.html未注册消息监听器,导致消息无人接收。
  2. chrome.tabs.onUpdated回调直接发送消息,未先确认Offscreen文档是否创建,也未处理发送异常。
  3. 主Worker的消息监听逻辑中,发送消息未明确接收方,存在消息无目标的情况。

错误修复步骤

1. 给Offscreen页面添加消息监听器

创建offscreen.js并引入到offscreen.html中,实现消息接收逻辑:

// offscreen.js
chrome.runtime.onMessage.addListener((msg) => {
  if (msg.offscreen) {
    switch(msg.type) {
      case "play":
        // 此处编写音频播放逻辑
        console.log("触发播放:", msg.play);
        break;
      case "pause":
        // 此处编写音频暂停逻辑
        console.log("触发暂停");
        break;
    }
  }
});

在offscreen.html中引入该脚本:

<!-- offscreen.html -->
<!DOCTYPE html>
<html>
<body>
  <script src="offscreen.js"></script>
</body>
</html>

2. 修正Worker中的消息发送逻辑

确保发送消息前Offscreen文档已创建,并处理发送异常:

async function createOffscreen() {
  if (await chrome.offscreen.hasDocument()) return;
  await chrome.offscreen.createDocument({
    url: "offscreen.html",
    reasons: ["AUDIO_PLAYBACK"],
    justification: "testing",
  });
  // 短暂等待Offscreen页面完成监听器注册
  await new Promise(resolve => setTimeout(resolve, 100));
}

chrome.runtime.onMessage.addListener(async (msg) => {
  switch (msg.type) {
    case "play":
      await createOffscreen();
      try {
        await chrome.runtime.sendMessage({
          type: "play",
          play: msg.play,
          offscreen: true,
        });
      } catch (err) {
        console.error("发送播放消息失败:", err);
      }
      break;
    case "pause":
      await createOffscreen();
      try {
        await chrome.runtime.sendMessage({ type: "pause", offscreen: true });
      } catch (err) {
        console.error("发送暂停消息失败:", err);
      }
      break;
  }
});

chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
  // 仅在URL实际变更时触发
  if (changeInfo.url) {
    await createOffscreen();
    try {
      await chrome.runtime.sendMessage({ type: "pause", offscreen: true });
    } catch (err) {
      console.error("URL变更时发送暂停消息失败:", err);
    }
  }
});

URL变更时发送消息的替代实现方法

除chrome.tabs.onUpdated外,还有以下更精准的实现方式:

方法1:使用chrome.webNavigation.onCompleted

该事件在页面加载完成(URL变更完成)时触发,避免重复触发:

// 需要在manifest.json中声明"webNavigation"权限
chrome.webNavigation.onCompleted.addListener(async (details) => {
  await createOffscreen();
  try {
    await chrome.runtime.sendMessage({ type: "pause", offscreen: true });
  } catch (err) {
    console.error("发送消息失败:", err);
  }
}, { url: [{ schemes: ["http", "https"] }] }); // 仅监听HTTP/HTTPS页面

方法2:通过Content Script监听SPA路由变化

针对单页应用(SPA)的路由跳转,注入Content Script监听页面内URL变化:

  1. 在manifest.json中声明Content Script:
"content_scripts": [
  {
    "matches": ["<all_urls>"],
    "js": ["content.js"]
  }
]
  1. 创建content.js:
// 监听浏览器前进/后退的路由变化
window.addEventListener("popstate", () => {
  chrome.runtime.sendMessage({ type: "url_changed", url: window.location.href });
});

// 监听初始页面加载
chrome.runtime.sendMessage({ type: "url_changed", url: window.location.href });
  1. 在worker.js中接收消息并处理:
chrome.runtime.onMessage.addListener(async (msg) => {
  if (msg.type === "url_changed") {
    await createOffscreen();
    try {
      await chrome.runtime.sendMessage({ type: "pause", offscreen: true });
    } catch (err) {
      console.error("发送暂停消息失败:", err);
    }
  }
});

方法3:监听标签页切换时的URL变化

结合chrome.tabs.onActivated和chrome.tabs.get,监听标签页切换后的URL变更:

chrome.tabs.onActivated.addListener(async (activeInfo) => {
  const tab = await chrome.tabs.get(activeInfo.tabId);
  if (tab.url) {
    await createOffscreen();
    try {
      await chrome.runtime.sendMessage({ type: "pause", offscreen: true });
    } catch (err) {
      console.error("发送消息失败:", err);
    }
  }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 22:00:57