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

Chrome扩展异步sendMessage无法通过sendResponse完成回调问题

问题描述

使用async chrome.runtime.sendMessage()时遇到问题:希望发送消息触发标签页URL导航,在导航完成后再返回响应,但嵌套在tabs.onUpdated监听器中的sendResponse()调用无法让原消息监听完成回调。已在消息监听器中返回true标记异步处理,后台也确认响应已发送,但将sendResponse()移到外层消息监听器时功能正常。

尝试代码

background.ts

chrome.runtime.onMessage.addListener(
  (
    message: { action: string; url?: string; tabId?: number },
    sender,
    sendResponse
  ) => {

    if (message.action === "navigate" && message.url) {

      (async () => {
        const navigateListener = (tabId: number, changeInfo: any) => {
          if (changeInfo.status === "complete") {
            sendResponse("Navigation Complete");
            chrome.tabs.onUpdated.removeListener(navigateListener); // Cleanup listener
          }
        };

        // Register listener before initiating navigation to avoid missing the event
        chrome.tabs.onUpdated.addListener(navigateListener);

        const activeTab = await getActiveTabId();

        chrome.tabs.update(activeTab, { url: message.url }, (tab) => {
          console.log("Updating tab...");
          // If the tab cannot be updated or the URL is loaded instantly, consider additional handling
          if (chrome.runtime.lastError || !tab) {
            console.error("Navigation failed or tab was closed.");
            chrome.tabs.onUpdated.removeListener(navigateListener); // Cleanup listener if necessary
          }
        });
      })();

      return true;
    }
  }
);

content_script.ts

const navMessage: NavigateMessage = {
  action: "navigate",
  url: `https://www.example.com`,
  tabId,
};

const navRes = await chrome.runtime.sendMessage(navMessage);
问题原因
  • 当前tabs.onUpdated监听器未过滤目标标签ID,会监听所有标签页的更新事件,可能导致sendResponse()被非目标标签的事件触发,或目标标签的事件被遗漏
  • 未在导航失败的分支中主动返回响应,导致消息回调可能一直处于等待状态
修复方案

修改background.ts代码,为tabs.onUpdated添加标签ID过滤,并完善异常分支的响应逻辑:

chrome.runtime.onMessage.addListener(
  (
    message: { action: string; url?: string; tabId?: number },
    sender,
    sendResponse
  ) => {

    if (message.action === "navigate" && message.url) {
      (async () => {
        // 确定目标标签ID:优先用消息传入的tabId,否则获取当前激活标签
        const targetTabId = message.tabId || await getActiveTabId();
        const navigateListener = (tabId: number, changeInfo: any, tab: chrome.tabs.Tab) => {
          // 只响应目标标签的加载完成事件,可选校验URL匹配避免误触发
          if (tabId === targetTabId && changeInfo.status === "complete" && tab.url === message.url) {
            sendResponse("Navigation Complete");
            chrome.tabs.onUpdated.removeListener(navigateListener);
          }
        };

        chrome.tabs.onUpdated.addListener(navigateListener);

        chrome.tabs.update(targetTabId, { url: message.url }, (tab) => {
          console.log("Updating tab...");
          if (chrome.runtime.lastError || !tab) {
            console.error("Navigation failed or tab was closed.");
            sendResponse("Navigation Failed"); // 主动返回错误响应
            chrome.tabs.onUpdated.removeListener(navigateListener);
          }
        });
      })();

      return true;
    }
  }
);
补充说明
  • 必须过滤目标标签ID,否则其他标签页的加载事件会干扰响应逻辑
  • 可选添加URL匹配校验,防止同标签跳转其他地址时误触发响应
  • 导航失败时主动调用sendResponse(),避免消息回调长期挂起

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 14:35:07