news 2026/10/22 6:33:33

工作者线程 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/10/21 15:40:08

长沙网安培训“潜规则”:只分两种,湖南网安基地和其他

摘要:​ 在长沙想成为网络安全工程师?你会发现市场看似选择众多,但懂行的人只会告诉你一个真相:要么选湖南网安基地,要么就是在“试错”。这篇文章为你深度剖析长沙网安培训的行业现状,告诉你为什么湖南网安…

作者头像 李华
网站建设 2026/10/22 2:32:01

Notepad++在数据处理中的高效应用案例

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 创建一个Notepad宏脚本,用于自动化处理日志文件。功能包括:按时间戳过滤日志条目,高亮显示错误和警告信息,统计各类消息出现频率&…

作者头像 李华
网站建设 2026/10/21 19:09:42

Vulkan教程(七):物理设备与队列族,选择合适的显卡并理解队列机制

目录 一、物理设备选择流程 1.1 扩展代码框架 1.1.1 添加初始化函数调用 1.1.2 添加物理设备成员变量 1.2 枚举系统中的物理设备 二、设备适配性检查 2.1 基础设备信息查询 2.2 简单适配性判断 2.3 加权评分选择(进阶方案) 2.4 本教程的适配性筛选逻辑 三、队列族…

作者头像 李华
网站建设 2026/10/21 8:04:41

“降重不是‘文字马赛克’,是学术表达的‘二次创作’——宏智树AI降重降AIGC,让AI生成内容重获‘人味儿’”

在AI写作席卷学术圈的今天,一个新困境悄然浮现: 你用AI高效写出了初稿,却被导师或查重系统无情标记:“疑似AIGC生成”“语言模板化”“缺乏个人风格”。 于是,你开始疯狂改写——同义词替换、语序倒装、删减句子……结…

作者头像 李华
网站建设 2026/10/22 1:30:53

Vulkan教程(十一):图像视图,Vulkan 图像的访问接口

目录 一、代码框架扩展 1.1 添加图像视图成员变量 1.2 添加函数调用 二、图像视图的创建逻辑 2.1 基础配置初始化 2.2 关键参数解析 1. 颜色通道重映射(components) 2. 子资源范围(subresourceRange) 3. 视图类型(viewType) 2.3 批量创建交换链图像视图 三、图…

作者头像 李华