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

Chrome扩展manifest v3中tabs.onUpdated.addListener报错排查

Chrome扩展Manifest V3消息通信错误分析与优化建议

问题描述

开发Chrome扩展(Manifest V3)时,使用chrome.tabs.onUpdated.addListener频繁触发错误:Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist.,对background.js与content.js的消息通信机制存疑,附上相关代码寻求问题分析及优化建议。

问题原因

  1. 消息发送时机与content script注入不同步
    即使判断了changeInfo.status === 'complete',页面加载完成的瞬间,浏览器可能还没完成content.js的注入,此时调用chrome.tabs.sendMessage会找不到接收端,直接报错。

  2. 非匹配页面也触发消息发送
    content script仅配置了特定域名的匹配规则,但chrome.tabs.onUpdated会监听所有标签页的更新事件。当打开非目标域名的页面时,background依然发送消息,而这些页面没有注入content.js,自然会出现接收端不存在的错误。

  3. Manifest V3 Service Worker的特性影响
    background采用Service Worker实现,浏览器会在闲置时将其休眠或销毁,重新激活时可能重复绑定监听,但核心问题还是发送时机与接收端存在性不匹配。

优化方案

方案一:精准匹配目标页面+捕获发送错误

在发送消息前,先判断当前标签页的URL是否匹配content script的规则,同时用try-catch包裹发送逻辑,避免错误抛出:

chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
  // 定义content script匹配的域名规则
  const targetPatterns = [
    "https://prisjakt.prismic.io/*",
    "https://www.prisjakt.nu/*",
    "https://www.prisjakt.no/*",
    "https://www.prisjagt.dk/*",
    "https://hintaopas.fi/*",
    "https://ledenicheur.fr/*",
    "https://pricespy.co.uk/*",
    "https://pricespy.co.nz/*"
  ];
  // 检查当前URL是否匹配目标规则
  const isTargetPage = targetPatterns.some(pattern => new URLPattern(pattern).test(tab.url));

  if (changeInfo.status === 'complete' && tab.status === 'complete' && isTargetPage) {
    try {
      await chrome.tabs.sendMessage(tabId, { type: "RELOADED" });
    } catch (err) {
      console.log("消息发送失败(content script未就绪):", err);
    }
  }
});

注:URLPattern是Chrome 95+支持的API,可准确校验URL是否符合manifest中的匹配规则。

方案二:让content script主动处理逻辑(推荐)

放弃background主动推送消息的模式,改为content script注入后直接执行页面逻辑——因为content script仅在匹配页面注入,无需跨页面通信,从根源避免接收端不存在的问题:

function handlePageLogic() {
  const prismicUrl = document.location.href;
  
  const prismicUrlMustExist = /~b/;
  const prismicUrlMustExist2 = /&b=/;
  const articleUrlMustExist = /--ec/;
 
  if (prismicUrlMustExist.test(prismicUrl) || prismicUrlMustExist2.test(prismicUrl)) {
    console.info("Hittade artikel. Väntar en sekund.");
    setTimeout(() => initiate(), 1000);
    console.info("Försöker hitta sidebar.");
  } else if (articleUrlMustExist.test(prismicUrl)) {
    console.info("Hittaden artikel på sajten.");
    setTimeout(() => initiate_article(), 1000);
  } else {
    console.warn("Error: hittade ingen kompatibel sida.");
  }
}

// content script默认在document_idle时机注入,此时页面已加载完成,直接执行逻辑
handlePageLogic();

// 监听页面刷新,确保逻辑重新执行
window.addEventListener('load', handlePageLogic);

方案三:调整content script注入时机

在manifest.json的content_scripts配置中显式声明run_at为document_idle(默认值),确保content script在页面完全加载后注入,减少时机不匹配的概率:

"content_scripts": [
  {
    "js": ["content.js"],
    "matches": [/* 你的匹配规则 */],
    "run_at": "document_idle"
  }
]

此方案可靠性不如方案二,页面complete状态与content script注入仍可能存在细微时间差。

原代码参考

background.js

chrome.tabs.onUpdated.addListener ( function (tabId, changeInfo, tab) {

  if (changeInfo.status === 'complete' && tab.status === 'complete' && tab.url) {
    chrome.tabs.sendMessage(tab.id, { type: "RELOADED" });
    
  }
});

content.js

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.type === "RELOADED") {

    let prismicUrl = document.location.href;
    
    const prismicUrlMustExist = /~b/; // Normal
    const prismicUrlMustExist2 = /&b=/; // Efter sökning
    const articleUrlMustExist = /--ec/;
   
    if (prismicUrlMustExist.test(prismicUrl) || prismicUrlMustExist2.test(prismicUrl)) {
      console.info("Hittade artikel. Väntar en sekund.");
      setTimeout(() => {  initiate(); }, 1000);
      console.info("Försöker hitta sidebar.");
    } else if (articleUrlMustExist.test(prismicUrl)) {
      console.info("Hittaden artikel på sajten.");
      setTimeout(() => {  initiate_article(); }, 1000);
    } else {
      console.warn("Error: hittade ingen kompatibel sida.");
    }
  }
});

manifest.json

{
  "name": "Links in Prismic",
  "action": {},
  "manifest_version": 3,
  "version": "0.7.5",
  "description": "Adds useful functions to Prismic when working with articles and products.",
  "permissions": [
    "activeTab",
    "scripting",
    "contextMenus",
    "tabs"
  ],
  "icons": { "16": "/images/icon16.png",
             "48": "/images/icon48.png",
             "128": "/images/icon128.png" },
  "background": {
    "service_worker": "background.js",
    "type": "module"
  },
  "options_page": "options.html",
  "content_scripts": [
    {
      "js": [
        "content.js"
      ],
      "matches": [
        "https://prisjakt.prismic.io/*",
        "https://www.prisjakt.nu/*",
        "https://www.prisjakt.no/*",
        "https://www.prisjagt.dk/*",
        "https://hintaopas.fi/*",
        "https://ledenicheur.fr/*",
        "https://pricespy.co.uk/*",
        "https://pricespy.co.nz/*"
       
      ]
    }
  ]
  
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 09:52:56