一、初识 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. FastDFS客户端与自定义文件存储系统

    <1>安装 安装提供给大家的fdfs_client-py-master.zip到虚拟环境中 pip install fdfs_client-py-master.zip pip instal ...

  2. vue实现一个简易Popover组件

    概述 之前写vue的时候,对于下拉框,我是通过在组件内设置标记来控制是否弹出的,但是这样有一个问题,就是点击组件外部的时候,怎么也控制不了下拉框的关闭,用户体验非常差. 当时想到的解决方法是:给根实例 ...

  3. JavaScript 数组方法

    数组方法: 1.Array.join([param]) 方法:将数组中所有的元素都转换为字符串并连接起来,通过字符 param 连接,默认使用逗号,返回最后生成的字符串 2.Array.reverse ...

  4. 微信APP支付,支付宝APP支付demo

    最近公司新开发的APP中,需要集成微信支付和支付宝支付,2个平台申请的都是APP支付.这是个人第一次单独的,完整的做完2个平台的支付. 这里我主要用到了2个接口:支付接口,订单查询接口,虽然2个平台的 ...

  5. Python - 关于代码阅读的一些建议

    初始能力 让阅读思路保持清晰连贯,主力关注在流程架构和逻辑实现上,不被语法.技巧和业务流程等频繁地阻碍和打断. 建议基本满足以下条件,再开始进行代码阅读: 具备一定的语言基础:熟悉基础语法,常用的函数 ...

  6. c++模板参数——数值类型推断

    模板类中,或模板函数中,若限定模板参数为数值类型,可以使用如下方式进行判断. template<typename T> Fmt::Fmt(const char *fmt, T val) { ...

  7. Redis 如何分析慢查询操作?

    什么是慢查询 和mysql的慢SQL日志分析一样,redis也有类似的功能,来帮助定位一些慢查询操作. Redis slowlog是Redis用来记录查询执行时间的日志系统. 查询执行时间指的是不包括 ...

  8. vue 国际化i18n 多语言切换

    安装 npm install vue-i18n 新建一个文件夹 i18n ,内新建 en.js zh.js index.js 三个文件 准备翻译信息 en.js export default { ho ...

  9. Android--UI之ListView

    前言 今天讲解一下Android平台下ListView控件的开发,在本篇博客中,将介绍ListView的一些常用属性.方法及事件,还会讲解ListView在开发中常用的几种方式,以及使用不通用的适配器 ...

  10. Unity UI性能优化技巧

    本文将介绍一些提升Unity UI性能的技巧.更多优化技巧,可以观看Unity工程师Ian Dundore在Unite Europe 2017的演讲<使用Unity性能提升技巧>. 1.划 ...