MessageChannel 消息通道
一、初识 MessageChannel 对象
通过构造函数 MessageChannel() 可以创建一个消息通道,实例化的对象会继承两个属性:port1 和 port2
port1 和 port2 都是 MessagePort 对象,在这里是只读的,无法对其进行字面量赋值
不过可以给 port 添加属性
上图还体现了 MessagePort 对象具有 onmessage 和 onmessageerror 两个属性
这是两个回调方法,使用 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 消息通道的更多相关文章
- 渐进式web应用开发---Service Worker 与页面通信(七)
_ 阅读目录 一:页面窗口向 service worker 通信 二:service worker 向所有打开的窗口页面通信 三:service worker 向特定的窗口通信 四:学习 Messag ...
- SpringCloud简记_part2
Zookeeper服务注册与发现 1)Eureka停止更新了,你怎么办? https://github.com/Netflix/eureka/wiki 2)SpringCloud整合Zookeeper ...
- SpringCloud学习之Stream消息驱动【自定义通道】(十一)
如果不清楚本篇内容的,请务必先去看完上一篇再看本篇,否则阅读起来可能会有部分障碍和困难: 上一篇文章<SpringCloud学习之Stream消息驱动[默认通道](十)>我们简单用自定义通 ...
- SpringCloud实战9-Stream消息驱动
官方定义 Spring Cloud Stream 是一个构建消息驱动微服务的框架. 应用程序通过 inputs 或者 outputs 来与 Spring Cloud Stream 中binder 交互 ...
- Spring Cloud Stream如何消费自己生产的消息?
在上一篇<Spring Cloud Stream如何处理消息重复消费>中,我们通过消费组的配置解决了多实例部署情况下消息重复消费这一入门时的常见问题.本文将继续说说在另外一个被经常问到的问 ...
- Spring Cloud Stream如何处理消息重复消费?
最近收到好几个类似的问题:使用Spring Cloud Stream操作RabbitMQ或Kafka的时候,出现消息重复消费的问题.通过沟通与排查下来主要还是用户对消费组的认识不够.其实,在之前的博文 ...
- c#通过Redis实现轻量级消息组件
最近在开发一个轻量级ASP.NET MVC开发框架,需要加入日志记录,邮件发送,短信发送等功能,为了保持模块的独立性,所以需要通过消息通信的方式进行处理,为了保持框架在部署,使用,二次开发过程中的简易 ...
- SpringCloud之Spring Cloud Stream:消息驱动
Spring Cloud Stream 是一个构建消息驱动微服务的框架,该框架在Spring Boot的基础上整合了Spring Integrationg来连接消息代理中间件(RabbitMQ, Ka ...
- Spring Cloud Stream如何消费自己生产的消息
在上一篇<Spring Cloud Stream如何处理消息重复消费>中,我们通过消费组的配置解决了多实例部署情况下消息重复消费这一入门时的常见问题.本文将继续说说在另外一个被经常问到的问 ...
随机推荐
- Base 底层库开源项目总结
在Android开发中,我们经常使用一些开源的项目,一般情况下,这些开源项目都是基于开源的底层库进行的开发,以适配各自的用户场景.下面来列举一下本人收藏或Star的项目: 一.JavaCV 项目地址: ...
- Android开发之如何避免ANR(Keeping Your App Responsive)
一:什么是ANR 如果应用程序不能响应用户的输入了,那么就可以说应用ANR了. 如果需要运行一个耗时较长的操作的时候,不要把这个任务放在UI线程上运行,而是单独创建一个线程运行那些操作. 以下情况会出 ...
- Laravel 5.6: Specified key was too long error
Laravel 5.6: Specified key was too long error 在Laravel执行以下命令: php artisan migrate 这是由于Laravel5.6设置了数 ...
- 吴恩达机器学习笔记27-样本和直观理解2(Examples and Intuitions II)
二元逻辑运算符(BINARY LOGICAL OPERATORS)当输入特征为布尔值(0 或1)时,我们可以用一个单一的激活层可以作为二元逻辑运算符,为了表示不同的运算符,我们只需要选择不同的权重即可 ...
- 微信小程序实现显示和隐藏控件-头像-取值-bindblur事件
微信小程序实现显示和隐藏控件 .wxml: <view class=" {{showOrHidden?'show':'hidden'}}"></view> ...
- Java面试集合(六)
1. abstract抽象 什么是abstract,中文为抽象,从具体事物抽出,概括它们共同的方面,本质属性与关系等,称为抽象.看不见,摸不着的东西叫做抽象,抽象是人们对世界万物的感觉,用特定的图像表 ...
- 微信小程序支付接入实战
1. 微信小程序支付接入实战 1.1. 需求 最近接到一个小程序微信支付的需求,需要我写后台支持,本着能不自己写就不自己写的cv原则,在网上找到了些第三方程序,经过尝试后,最后决定了这不要脸作者的 ...
- remote: Incorrect username or password ( access token )
解决问题 进入控制面板 用户账号,选择管理您的凭据 修改凭据 修改完成后,保存即可
- jquery获取radio选中值及遍历
使用jquery获取radio的值,最重要的是掌握jquery选择器的使用,在一个表单中我们通常是要获取被选中的那个radio项的值,所以要加checked来筛选,比如有以下的一些radio项:1.& ...
- ubuntu设置IP地址&修改vi模式键盘上下键错位
解决ubuntu上面使用vi 出现方向键错乱的情况 编辑/etc/vim/vimrc.tiny 使用root权限操作:将“set compatible”改成“set nocompatible” 新增一 ...