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

Chrome扩展开发:如何在弹窗关闭时从内容脚本向其稳定发消息?

解决Chrome扩展弹窗关闭后内容脚本无法发送消息的问题

问题根源

当弹窗(popup)关闭时,它的JavaScript上下文会被Chrome销毁,对应的chrome.runtime.onMessage监听器也会失效。此时内容脚本(content.js)调用chrome.runtime.sendMessage找不到接收端,就会触发Could not establish connection. Receiving end does not exist.错误。

可行解决方案

方案1:通过后台Service Worker中转消息

利用Chrome扩展的后台Service Worker作为持久化的消息中转层,内容脚本先把标题发送到后台存储,弹窗打开时再从后台获取数据。

步骤1:配置manifest.json

确保已声明后台Service Worker:

{
  "manifest_version": 3,
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [
    {
      "matches": ["*://*.youtube.com/watch*"],
      "js": ["content.js"]
    }
  ],
  "action": {
    "default_popup": "popup.html"
  }
}

步骤2:修改content.js

将消息发送给后台Service Worker:

window.onload = () => {
  const videoTitle = document.querySelector("#title h1 yt-formatted-string")?.textContent;
  if (videoTitle) {
    chrome.runtime.sendMessage({
      type: "VIDEO_NAME",
      value: videoTitle
    });
  }
};

步骤3:新增background.js

监听内容脚本的消息并存储视频标题,同时提供弹窗获取数据的接口:

let currentVideoTitle = "";

// 接收内容脚本的标题消息
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.type === "VIDEO_NAME") {
    currentVideoTitle = request.value;
  }
});

// 响应弹窗的标题请求
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.type === "GET_VIDEO_NAME") {
    sendResponse(currentVideoTitle);
  }
});

步骤4:修改popup.js

弹窗打开时主动从后台获取存储的标题:

document.addEventListener('DOMContentLoaded', async () => {
  const response = await chrome.runtime.sendMessage({ type: "GET_VIDEO_NAME" });
  if (response) {
    // 假设弹窗内有id为title-display的元素用于展示标题
    document.getElementById("title-display").textContent = response;
  }
});

方案2:直接用chrome.storage存储标题

跳过后台脚本,内容脚本直接把标题存入Chrome本地存储,弹窗打开时读取存储的数据。

修改content.js

window.onload = () => {
  const videoTitle = document.querySelector("#title h1 yt-formatted-string")?.textContent;
  if (videoTitle) {
    chrome.storage.local.set({ currentVideoTitle: videoTitle });
  }
};

修改popup.js

document.addEventListener('DOMContentLoaded', async () => {
  const result = await chrome.storage.local.get("currentVideoTitle");
  if (result.currentVideoTitle) {
    document.getElementById("title-display").textContent = result.currentVideoTitle;
  }
});

方案对比

  • 方案1:适合需要在后台处理额外逻辑(如标题去重、格式过滤)的场景,但需要维护后台Service Worker的状态。
  • 方案2:代码更简洁,依赖Chrome原生存储API,适合简单的数据传递需求。

内容的提问来源于stack exchange,提问作者Adnan Arif Sait

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 01:45:35