跳轉至

建立 2026-09-17 更新 2026-09-17

訊息傳遞

Background Service Worker、Content Script、Popup/Options 頁面各自執行在獨立、互相隔離的環境中,無法直接呼叫彼此的函式或共用變數。訊息傳遞(message passing)是它們之間唯一的溝通方式,理解它就能把 核心架構 提到的各個元件真正串起來。

一次性訊息:sendMessage / onMessage

最常用的模式,適合「問一句、答一句」的情境。

Content Script 或 Popup:發送訊息
chrome.runtime.sendMessage({ type: "GET_NOTES" }, (response) => {
  console.log("收到的筆記:", response);
});
Background:接收並回應
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.type === "GET_NOTES") {
    chrome.storage.local.get("notes", (result) => {
      sendResponse(result.notes ?? []);
    });
    return true; // 必須回傳 true,Chrome 才會等待非同步的 sendResponse
  }
});

return true 是最容易忽略的細節:onMessage 的監聽器預設是同步的,一執行完就會關閉溝通通道;如果 sendResponse 是在 chrome.storage.local.get 的回呼裡才呼叫(非同步),沒有回傳 true,回應就會遺失。

對特定分頁送訊息:tabs.sendMessage

chrome.runtime.sendMessage 送出的訊息只有 Background 與其他擴充功能頁面收得到,收不到 Content Script 的訊息。要主動通知某個分頁的 Content Script,要用 chrome.tabs.sendMessage 並指定 tabId

Background:通知目前分頁的 Content Script
chrome.action.onClicked.addListener(async (tab) => {
  const response = await chrome.tabs.sendMessage(tab.id, { type: "HIGHLIGHT" });
  console.log(response);
});

反過來,Content Script 要送訊息給 Background,一律用 chrome.runtime.sendMessage(不能用 tabs.sendMessage,因為 Background 沒有 tabId)。

長連線:runtime.connect

如果需要持續、多次來回傳遞訊息(例如即時同步輸入內容),一問一答的 sendMessage 每次都要重新建立通道,效率較差,這時適合用 chrome.runtime.connect 建立長連線(Port):

建立連線端
const port = chrome.runtime.connect({ name: "sync-channel" });
port.postMessage({ type: "PING" });
port.onMessage.addListener((msg) => console.log("收到:", msg));
接收連線端
chrome.runtime.onConnect.addListener((port) => {
  port.onMessage.addListener((msg) => {
    port.postMessage({ type: "PONG", received: msg });
  });
});

該用哪一種?

情境 建議
單次請求、單次回應 sendMessage / onMessage
通知特定分頁的 Content Script tabs.sendMessage
需要持續、高頻率的雙向溝通 runtime.connect(長連線 Port)

下一步

掌握訊息傳遞後,核心架構 四大元件就完整串起來了。接著前往 常用 API,深入認識 chrome.storagechrome.tabs 等最常用的 API。