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

Chrome扩展Manifest V3消息传递丢失Map对象问题排查

问题

开发Chrome扩展时,通过content script抓取数据并将包含字符串、整数、数组及3个Map对象的复合对象传递给background worker,传递过程中Map对象被剥离——发送前和接收后打印对象,发现原本的Map属性变为空对象。相关代码示例如下:

内容脚本代码

chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
    if (msg.attemptedStartScrapping) {
        try {
            fetchInfo()
                .then(info => {
                    console.log({content: info})
                    sendResponse(info)
                })
            return true
        } catch (e) {
            if(!(e instanceof NotHomepageException)) console.error(e)
        }
    }
})

后台工作线程代码

chrome.action.onClicked.addListener(tab => {
    const details = { tabId: tab.id }
    sendMessage(details)
})

function sendMessage(details) {
    chrome.tabs.sendMessage(
        details.tabId,
        {
            attemptedStartScrapping: true,
            tabId: details.tabId ?? null,
        },
        info => {
            console.log({ worker: info })
        }
    )
}

控制台输出说明

  • 内容脚本控制台:打印的info对象包含完整的Map属性,数据正常
  • 后台控制台:接收到的info对象中,原Map属性变为空对象

这是消息传递的bug吗?

解决方案

这不是Chrome扩展消息传递的bug,而是消息传递的序列化机制限制导致的。Chrome扩展的runtime.sendMessage/tabs.sendMessage使用JSON序列化传递数据,而原生JSON不支持Map、Set、Date等复杂类型的序列化——当序列化Map时,会被转换为空对象{},因此接收端无法拿到原Map数据。

解决方法是在发送前将Map转换为JSON可序列化的格式,接收后再还原为Map:

步骤1:发送端(content script)转换Map

修改fetchInfo的处理逻辑,将对象中的Map转换为数组或普通对象:

fetchInfo().then(info => {
    // 将Map转换为可序列化的数组格式
    const serializableInfo = {
        ...info,
        map1: Array.from(info.map1),
        map2: Array.from(info.map2),
        map3: Array.from(info.map3)
        // 也可转为普通对象:Object.fromEntries(info.map1)
    }
    console.log({content: serializableInfo})
    sendResponse(serializableInfo)
})

步骤2:接收端(background worker)还原Map

在接收回调中将数组或普通对象还原为Map:

chrome.tabs.sendMessage(
    details.tabId,
    { attemptedStartScrapping: true, tabId: details.tabId ?? null },
    info => {
        // 还原Map结构
        const restoredInfo = {
            ...info,
            map1: new Map(info.map1),
            map2: new Map(info.map2),
            map3: new Map(info.map3)
            // 若之前转成普通对象,用new Map(Object.entries(info.map1))还原
        }
        console.log({ worker: restoredInfo })
    }
)

注意事项

  • 除Map外,Set、Date、RegExp等复杂类型也会遇到类似序列化问题,需按相同逻辑处理
  • 若对象嵌套较深,建议编写递归转换函数,自动处理所有嵌套的复杂类型

内容的提问来源于stack exchange,提问作者César Rodriguez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 08:03:34