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

Chrome扩展Manifest V3:popup与content脚本通信报错排查

Chrome扩展Manifest V3消息通信错误排查

错误现象

开发基于Manifest V3的Chrome扩展时,点击popup中的按钮偶尔触发以下错误:

Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist.

错误触发在调用chrome.tabs.sendMessage向content脚本发送消息的代码行。

相关代码

const sendStartSignal = document.getElementById("start-timer");
sendStartSignal.onclick = async function (e)
{
    ...

    // Get the current tab
    let tab = await getCurrentTab()
    // only send a message if you watching a youtube video
    if(typeof tab !== 'undefined' && tab.url.includes("youtube.com/watch")){
        const response = await chrome.tabs.sendMessage(
            tab.id,
            { workTime: workTime,
              restTime: restTime, }
        );
    }
    else{
        console.error("No youtube video on tab.")
    }
};// ERROR SHOWS IT HAPPENING ON THIS LINE

async function getCurrentTab() {
    let queryOptions = { active: true, lastFocusedWindow: true };
    // `tab` will either be a `tabs.Tab` instance or `undefined`.
    let [tab] = await chrome.tabs.query(queryOptions);
    return tab;
}

content.js

chrome.runtime.onMessage.addListener(
    function (request, sender, sendResponse){
        sendResponse({status: "recieved tab with YouTube video"});
        startTimer(document.querySelector('video'), request.workTime, request.restTime);
});

function startTimer(video, workTime, restTime) {
    
    ... 

    const intervalId = setInterval(() => {

        ...

    }, 1000);

}

Manifest配置片段

"permissions": [
        "scripting",
        "activeTab",
        "tabs",
    ],
"content_scripts": [
  {
    "js": ["./scripts/content.js"],
    "matches": ["*://*.youtube.com/watch*"]
  }
]

问题解答

是否存在未捕获的Promise?

是,未捕获的Promise出现在chrome.tabs.sendMessage的调用位置。

原因分析

  1. chrome.tabs.sendMessage是异步方法,返回一个Promise。当接收端(content脚本)不存在时,这个Promise会被reject,但代码里没有用try/catch包裹该异步调用,导致rejected的Promise未被捕获,从而抛出Uncaught (in promise)错误。
  2. 接收端偶尔不存在的场景:
    • YouTube页面刚加载完成,content脚本还未完成注入;
    • YouTube是单页应用(SPA),页面通过路由跳转时,content脚本不会自动重新注入,导致接收端丢失;
    • 标签页URL匹配但实际页面状态未加载完成,content脚本未初始化。

修复建议

  • 用try/catch捕获消息发送失败的情况,还可以尝试重新注入content脚本后重试:
if(typeof tab !== 'undefined' && tab.url.includes("youtube.com/watch")){
    try {
        const response = await chrome.tabs.sendMessage(
            tab.id,
            { workTime: workTime, restTime: restTime }
        );
    } catch (err) {
        console.error("消息发送失败:", err);
        // 尝试重新注入content脚本
        await chrome.scripting.executeScript({
            target: { tabId: tab.id },
            files: ["./scripts/content.js"]
        });
        // 重新发送消息
        const response = await chrome.tabs.sendMessage(tab.id, { workTime, restTime });
    }
}
  • 优化content脚本注入时机:在Manifest的content_scripts配置中添加"run_at": "document_idle"(默认值)或"document_start",确保脚本在合适时机注入;
  • 针对SPA路由变化:在content脚本中监听popstate事件或YouTube自身的路由变化事件,确保消息监听始终有效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 07:50:20