news 2026/6/23 21:10:44

工作者线程 postMessage() 方法参数详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
工作者线程 postMessage() 方法参数详解

postMessage() 方法参数详解


postMessage()方法有两种形式:


1. Window.postMessage()

javascript

otherWindow.postMessage(message, targetOrigin, [transfer]);

2. Worker.postMessage() 和 MessagePort.postMessage()

javascript

worker.postMessage(message, [transfer]); // 或 port.postMessage(message, [transfer]);

参数说明

第一个参数:message(必需)

  • 要发送的数据
  • 可以是任何可序列化的 JavaScript 对象
  • 浏览器会使用结构化克隆算法来复制数据
  • 可以包含循环引用

第二个参数:targetOrigin(仅 Window.postMessage 需要)

  • 指定目标窗口的源(协议+主机+端口号)
  • 用于安全检查,防止消息发送到错误的域
  • 可以设置为 "*" 表示不限制目标源(不推荐)

  • targetOrigin

    • 指定哪些窗口能接收消息

    • 可以是具体的域名(如 "https://example.com")或通配符:

      • "*":发送到任何窗口(不安全)

      • "/":发送到同源窗口

第三个参数:transfer(可选)

  • 一个数组,包含需要转移所有权的对象
  • 主要用于 Transferable 对象,如 ArrayBuffer、MessagePort 等
  • 转移后,发送方将失去对这些对象的访问权限

可转移对象类型

// 1. ArrayBuffer const buffer = new ArrayBuffer(1024); window.postMessage(buffer, '*', [buffer]); // buffer 现在在发送方变为不可用 // 2. MessagePort const channel = new MessageChannel(); window.postMessage('message', '*', [channel.port2]); // 3. ImageBitmap const imageBitmap = await createImageBitmap(image); window.postMessage({ image: imageBitmap }, '*', [imageBitmap]); // 4. OffscreenCanvas const offscreen = new OffscreenCanvas(256, 256); window.postMessage({ canvas: offscreen }, '*', [offscreen]);

可转移对象 vs 结构化克隆

结构化克隆(默认行为)

const worker = new Worker('./worker.js'); const buffer = new ArrayBuffer(8); console.log('发送前 buffer 大小:', buffer.byteLength); // 8 // 结构化克隆 - 数据被复制 worker.postMessage(buffer); console.log('发送后 buffer 大小:', buffer.byteLength); // 8 (仍然可以访问)

可转移对象

const worker = new Worker('./worker.js'); const buffer = new ArrayBuffer(8); console.log('发送前 buffer 大小:', buffer.byteLength); // 8 // 转移对象 - 所有权转移给 worker worker.postMessage(buffer, [buffer]); console.log('发送后 buffer 大小:', buffer.byteLength); // 0 (失去访问权限)

使用示例

基本使用

javascript

// 父窗口发送消息 const iframe = document.querySelector('iframe'); const buffer = new ArrayBuffer(1024); // 转移 buffer 所有权 iframe.contentWindow.postMessage( { type: 'data', buffer }, 'https://example.com', [buffer] // buffer 被转移 ); console.log(buffer.byteLength); // 0 - 已不可用

多个可转移对象

javascript

const buffer1 = new ArrayBuffer(256); const buffer2 = new ArrayBuffer(512); const channel = new MessageChannel(); parentWindow.postMessage( { buffers: [buffer1, buffer2], port: channel.port1 }, '*', [buffer1, buffer2, channel.port1] // 转移所有对象 );

重要注意事项


1.所有权转移是永久性的

javascript

const buffer = new ArrayBuffer(1024); postMessage(buffer, '*', [buffer]); // 错误!buffer 已转移,不能再使用 const view = new Uint8Array(buffer); // TypeError

2.只能转移特定的对象类型

尝试转移不可转移的对象会抛出错误:

javascript

const obj = { name: 'test' }; postMessage(obj, '*', [obj]); // TypeError: Value at index 0 is not transferable

3.性能优势

转移比复制更高效,特别对于大型数据:

javascript

// 复制方式(占用双倍内存) const largeBuffer = new ArrayBuffer(100 * 1024 * 1024); // 100MB postMessage({ data: largeBuffer }, '*'); // 完整复制 // 转移方式(零拷贝) postMessage(largeBuffer, '*', [largeBuffer]); // 仅转移所有权

4.接收方处理

javascript

// 接收方 window.addEventListener('message', (event) => { if (event.data.buffer) { // buffer 的所有权现在属于这个上下文 const view = new Uint8Array(event.data.buffer); // 使用 view... // 可以选择再转移回去 event.source.postMessage('done', '*', [event.data.buffer]); } });

实际应用场景


高性能图像处理

javascript

// 主线程 → Worker const offscreen = new OffscreenCanvas(800, 600); const bitmap = offscreen.getContext('2d').getImageData(0, 0, 800, 600); worker.postMessage({ bitmap }, '*', [bitmap]);

音频数据处理

javascript

// 处理音频流 const audioBuffer = audioContext.createBuffer(2, 44100, 44100); worker.postMessage({ audio: audioBuffer }, '*', [audioBuffer]);

WebGL纹理共享

javascript

// 共享纹理数据 const gl = canvas.getContext('webgl'); const texture = gl.createTexture(); // ...设置纹理数据 offscreenCanvas.transferToImageBitmap(); // 转移到 Worker 进行处理

浏览器兼容性

  • 所有现代浏览器都支持基本的postMessage()

  • 可转移对象支持:

    • ArrayBuffer: Chrome 13+, Firefox 18+, Safari 6+

    • MessagePort: Chrome 59+, Firefox 59+, Safari 11.1+

    • ImageBitmap: Chrome 52+, Firefox 51+, Safari 11.1+


最佳实践

  1. 始终指定具体的 targetOrigin,避免使用"*"

  2. 验证消息来源


javascript

window.addEventListener('message', (event) => { if (event.origin !== 'https://trusted-domain.com') return; // 处理消息 });

  1. 及时释放资源:转移后主动清理引用

  2. 错误处理:处理转移失败的情况


transfer参数是实现高性能跨线程/跨文档通信的关键特性,特别适用于处理大型二进制数据。


关键要点总结

  1. 结构化克隆:默认情况下,postMessage 会对传输的数据进行深拷贝,发送方保留数据副本。

  2. 可转移对象:通过 transfer 数组指定的对象会转移所有权,发送方失去访问权限,接收方获得所有权。

  3. 性能优势:对于大型数据(如 ArrayBuffer),使用可转移对象可以显著提高性能,避免不必要的数据复制。

  4. 适用对象:常见的可转移对象包括 ArrayBuffer、MessagePort、ImageBitmap 等。

  5. 使用场景:适用于需要在主线程和 worker 之间高效传输大量数据的情况,例如图像处理、音频数据处理等。


这种方式特别适合需要高性能数据传输的场景,因为它避免了复制大型数据结构的开销。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/23 16:04:43

“期刊论文不是‘投稿机器’,是科学对话的邀请函——宏智树AI期刊论文功能,让每一篇投稿都自带‘学术社交力’”

在科研圈里,有一句心照不宣的话: “写论文难,投期刊更难。” 你可能熬了三个月写出一篇逻辑严密、数据扎实的论文,却在投稿时卡在“格式不符”“语言不专业”“创新点表达不清”上。 更糟的是,编辑拒稿信只写一句&…

作者头像 李华
网站建设 2026/6/22 22:51:11

Vulkan教程(十二):图形管线,Vulkan 渲染的核心流程

目录 一、图形管线核心阶段解析 1.1 输入装配器(Input Assembler) 1.2 顶点着色器(Vertex Shader) 1.3 细分着色器(Tessellation Shaders) 1.4 几何着色器(Geometry Shader) 1.5 光栅化阶段(Rasterization) 1.6 片段着色器(Fragment Shader) 1.7 颜色混合阶…

作者头像 李华
网站建设 2026/6/23 21:04:53

“场景化 + 利益前置” 风格拟定标题,从多学科适配、专业级控制、高效协作三大维度重构内容,突出宏智树 AI 绘图功能的差异化优势:

一、科研人的绘图困境:你是否也在为 “图” 所困? “实验数据完美,却栽在插图上”—— 这是无数科研工作者的共同痛点。用 Visio 画机制图要逐点拖拽,用 AI 生成的图表文字乱码,投稿时发现分辨率不达标,跨…

作者头像 李华
网站建设 2026/6/23 21:07:23

电商网站链接失效危机?快马AI解决方案全解析

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 开发一个电商网站链接维护系统,针对商品下架/链接失效场景提供:1)自动检测失效商品链接 2)基于历史数据智能推荐相似商品 3)生成美观的404替代页面包含推荐商…

作者头像 李华
网站建设 2026/6/23 21:05:44

为什么网站无法打开-eshukan.com

尊敬的用户您好: 您访问的网站被机房安全管理系统拦截,可能是以下原因造成14: 1.您的网站未备案,或者原备案号被取消,进入备案通道. 2.您的网站未添加网站白名单,添加网站白名单.如果已添加,请等…

作者头像 李华
网站建设 2026/6/23 21:07:37

AI如何解决TLS协议版本不匹配问题

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 开发一个AI工具,能够自动检测服务器和客户端之间的TLS协议版本兼容性。工具应支持扫描目标服务器支持的TLS版本,并与客户端请求的版本进行比对,自…

作者头像 李华