一、初识 MessageChannel 对象

通过构造函数 MessageChannel() 可以创建一个消息通道,实例化的对象会继承两个属性:port1port2

port1 和 port2 都是 MessagePort 对象,在这里是只读的,无法对其进行字面量赋值

不过可以给 port 添加属性

上图还体现了 MessagePort 对象具有 onmessageonmessageerror 两个属性

这是两个回调方法,使用 MessagePort.postMessage 方法发送消息的时候,就会触发另一个端口的 onmessage

消息通道就像是一条左右贯通的管道,左右两个端口就是 port1 和 port2

这两个端口可以相互发送消息,port1 发送的消息可以在 port2 接收到,反之亦然

二、多个 Web Worker 之间通信

MessageChannel 可以结合 Web Worker 实现多线程通信

// main.js

let worker1 = new Worker('./worker1.js');
let worker2 = new Worker('./worker2.js');
let ms = new MessageChannel();

// 把 port1 分配给 worker1
worker1.postMessage('main', [ms.port1]);
// 把 port2 分配给 worker2
worker2.postMessage('main', [ms.port2]);
worker2.onmessage = function(event) {
console.log(event.data);
}

这里的 postMessage() 可以接收两个参数:message、transferList

message 消息内容,可以是任意基础数据类型
transferList 由被传输对象组成的数组,这些对象的所有权会转移给调用 postMessage 的对象

所以上面的代码,就是把消息通道的 port1 分配给了 worker1,把 port2 分配给 worker2

也就是用消息通道,将两个 worker 给连接起来

// worker1.js
onmessage = function(e) {
if (e.data === 'main') {
const port = e.ports[0];
port.postMessage('Hi! I'm worker1');
}
}
// worker2.js
onmessage = function(e) {
if (e.data === 'main') {
const port = e.ports[0];
port.onmessage = function(e) {
postMessage(e.data);
}
}
}

代码运行的时候,worker1 中通过 port1 发送消息,然后 worker2 就能从 port2 中接收到消息

三、深拷贝

大部分需要深拷贝的场景,都可以使用以下代码:

JSON.parse(JSON.stringify(object))

但这种办法会忽略 undefined、function、symbol循环引用的对象

而通过 postMessage() 方法传输的 message 参数是深拷贝的

所以可以借用 MessageChannel 实现深拷贝:

// 深拷贝函数
function deepClone(val) {
return new Promise(resolve => {
const { port1, port2 } = new MessageChannel()
port2.onmessage = e => resolve(e.data)
port1.postMessage(val)
})
} // 定义一个包含 undefined 的对象
let obj = {
a: 'wise',
b: undefined,
c: {
d: 'wrong'
}
}
// 循环引用
obj.c.e = obj.c // 注意该方法是异步的
async function test() {
const clone = await deepClone(obj)
console.log(clone)
}
test()

但这个深拷贝只能解决 undefined 和循环引用对象的问题,对于 Symbol 和 function 依然束手无策

参考资料:

《HTML5 postMessage iframe跨域web通信简介》

《MessageChannel是什么,怎么使用?》

MessageChannel 消息通道的更多相关文章

  1. 渐进式web应用开发---Service Worker 与页面通信(七)

    _ 阅读目录 一:页面窗口向 service worker 通信 二:service worker 向所有打开的窗口页面通信 三:service worker 向特定的窗口通信 四:学习 Messag ...

  2. SpringCloud简记_part2

    Zookeeper服务注册与发现 1)Eureka停止更新了,你怎么办? https://github.com/Netflix/eureka/wiki 2)SpringCloud整合Zookeeper ...

  3. SpringCloud学习之Stream消息驱动【自定义通道】(十一)

    如果不清楚本篇内容的,请务必先去看完上一篇再看本篇,否则阅读起来可能会有部分障碍和困难: 上一篇文章<SpringCloud学习之Stream消息驱动[默认通道](十)>我们简单用自定义通 ...

  4. SpringCloud实战9-Stream消息驱动

    官方定义 Spring Cloud Stream 是一个构建消息驱动微服务的框架. 应用程序通过 inputs 或者 outputs 来与 Spring Cloud Stream 中binder 交互 ...

  5. Spring Cloud Stream如何消费自己生产的消息?

    在上一篇<Spring Cloud Stream如何处理消息重复消费>中,我们通过消费组的配置解决了多实例部署情况下消息重复消费这一入门时的常见问题.本文将继续说说在另外一个被经常问到的问 ...

  6. Spring Cloud Stream如何处理消息重复消费?

    最近收到好几个类似的问题:使用Spring Cloud Stream操作RabbitMQ或Kafka的时候,出现消息重复消费的问题.通过沟通与排查下来主要还是用户对消费组的认识不够.其实,在之前的博文 ...

  7. c#通过Redis实现轻量级消息组件

    最近在开发一个轻量级ASP.NET MVC开发框架,需要加入日志记录,邮件发送,短信发送等功能,为了保持模块的独立性,所以需要通过消息通信的方式进行处理,为了保持框架在部署,使用,二次开发过程中的简易 ...

  8. SpringCloud之Spring Cloud Stream:消息驱动

    Spring Cloud Stream 是一个构建消息驱动微服务的框架,该框架在Spring Boot的基础上整合了Spring Integrationg来连接消息代理中间件(RabbitMQ, Ka ...

  9. Spring Cloud Stream如何消费自己生产的消息

    在上一篇<Spring Cloud Stream如何处理消息重复消费>中,我们通过消费组的配置解决了多实例部署情况下消息重复消费这一入门时的常见问题.本文将继续说说在另外一个被经常问到的问 ...

随机推荐

  1. eclipse创建Maven web项目的步骤

    Maven 是一个项目管理工具,可以对 Java 项目进行构建.依赖管理. Maven 能够帮助开发者完成以下工作: 构建 文档生成 报告 依赖 SCMs 发布 分发 邮件列表 一.环境配置 Mave ...

  2. 腾迅云获取免费SSL证书并布置

    上次申请了SSL证书一直没时间布置,今天重新再来操作一次 首先需要申请SSL证书,腾迅云买的域名有免费一年的SSL证书申请,网址:https://console.cloud.tencent.com/s ...

  3. 10分钟看懂Docker和K8S

    本文来源:鲜枣课堂 2010年,几个搞IT的年轻人,在美国旧金山成立了一家名叫"dotCloud"的公司. 这家公司主要提供基于PaaS的云计算技术服务.具体来说,是和LXC有关的 ...

  4. JS创建对象,数组,函数的三种方式

    害怕自己忘记,简单总结一下 创建对象的3种方法 ①:创建一个空对象   var obj = {}; ②:对象字面量 var obj = { name: "Tom", age: 27 ...

  5. 《Java 多线程编程核心技术》- 笔记

    作为业务开发人员,能够在工作中用到的技术其实不多.虽然平时老是说什么,多线程,并发,注入,攻击!但是在实际工作中,这些东西不见得用得上.因为,我们用的框架已经把这些事做掉了. 比如web开发,外面有大 ...

  6. 原生Ajax GET+POST请求无刷新实现文本框用户名是否被注册

    实现Ajax需要使用一个核心对象XMLHttpRequest XMLHttpRequest对象可以在不向服务器提交整个页面的情况下,实现局部更新网页.当页面全部加载完毕后,客户端通过该对象向服务器请求 ...

  7. axios 安卓低版本兼容性处理

    问题: 在较低版本的android手机中发现封装的 http 无效,我测试使用的是android 4.4的老手机,主要就是无法使用promise. 解决方案 安装 npm install es6-pr ...

  8. Gradle实现自动打包,签名,自定义apk文件名

    Gradle实现自动打包,签名,自定义apk文件名 什么是签名,签名有什么用 Android APP都需要我们用一个证书对应用进行数字签名,不然的话是无法安装到Android手机上的,平时我们调试运行 ...

  9. mysql 开发基础系列8 表的存储引擎

    一. 表的存储引擎 1. 概述 插件式存储引擎是mysql数据库最重要的特性之一, 用户可以根据应用的需要选择如何存储和索引数据,是否使用事务等.在mysql 5.0里支持的引擎包括: MyISAM, ...

  10. app 性能

    Android App优化之性能分析工具 https://www.jianshu.com/p/da2a4bfcba68 -------------- 系列文: 背景:Android App优化, 要怎 ...