从postMessage接收的ArrayBuffer无法初始化Uint8Array问题
问题根因
JSON 本身不支持序列化 ArrayBuffer、Uint8Array 这类二进制类型,你在主页面把包含 ArrayBuffer 的数据做 JSON 序列化时,二进制对象会被强制转为普通键值对对象,反序列化后得到的只是和 ArrayBuffer 结构相似的普通 JS 对象,并非原生 ArrayBuffer 实例,自然不支持 slice 等原生方法,也无法用来初始化 Uint8Array。
TypeScript 的类型标注仅为编译期校验,不会改变运行时的实际类型,所以显式类型转换不会生效。
解决方案
方案1(推荐):使用 postMessage 原生结构化克隆能力,跳过 JSON 序列化
postMessage 自带的结构化克隆算法原生支持 ArrayBuffer 等二进制类型传输,同域场景下无需额外序列化处理,性能更好:
- 主页面发送逻辑调整:
// 直接传递ArrayBuffer实例,不要做JSON序列化 iframe.contentWindow.postMessage({ type: 'bufferData', buffer: targetArrayBuffer }, location.origin) // 如需优化性能还可以转移二进制所有权: // iframe.contentWindow.postMessage({buffer: targetArrayBuffer}, location.origin, [targetArrayBuffer])
- iframe 接收逻辑调整:
window.addEventListener('message', (e) => { if (e.origin !== location.origin) return if (e.data.type === 'bufferData') { // e.data.buffer 就是原生ArrayBuffer实例,可直接使用 myMessageDataHandler(e.data.buffer) } })
方案2:必须使用JSON序列化时提前做二进制转码
如果业务逻辑要求必须走JSON序列化,可在传输前把二进制转成可序列化的普通数组,接收后再转回ArrayBuffer:
- 主页面序列化前处理:
const uint8 = new Uint8Array(targetArrayBuffer) const serializableStr = JSON.stringify({ buffer: Array.from(uint8) })
- iframe 反序列化后还原:
const parsedData = JSON.parse(receivedStr) const uint8 = new Uint8Array(parsedData.buffer) const realBuffer = uint8.buffer myMessageDataHandler(realBuffer)
验证方法
你可以在 myMessageDataHandler 中加一行代码确认运行时类型:
console.log(Object.prototype.toString.call(buffer)) // 原生ArrayBuffer会输出 [object ArrayBuffer],如果输出 [object Object] 就是序列化导致的假对象
内容的提问来源于stack exchange,提问作者Rajat
相关产品推荐
相关产品推荐

