希沃ENOW大前端

公司官网:CVTE(广州视源股份)

团队:CVTE旗下未来教育希沃软件平台中心enow团队

「本文作者:」

前言

本系列共有以下几个章节:

  • 主进程与渲染进程的两情相悦

  • 渲染进程与渲染进程的搭桥牵线

  • 定情信物传声筒port

您此次阅读的是第三章节:定情信物传声筒port。

注:以上所有文章都被归档到:https://github.com/LinDaiDai/niubility-coding-js 中 ,案例都上传至:https://github.com/LinDaiDai/electron-ipc-example ,欢迎 Star,感谢 Star。

大纲

在之前的文章中,我们主要介绍了 ipcMainipcRenderer 是如何实现主进程与渲染进程、以及渲染进程与渲染进程进行通信的。大家不难发现,之前介绍的方式都非常依赖主进程,特别是渲染进程之间的通信,每次都需要主进程这个中间人来传话,难道就没有什么更简单点的方式吗?

咦,这还真有一个,那就是利用 MessagePort ,通俗易懂的翻译过来:消息端口...(啪,就你英语好是吧)

大家别急,还不知道是啥玩意的话,让我来给大家介绍一下。用个小故事来简单举个例子哈:

渲染进程一(某先生)和渲染进程二(某女士)通过媒人介绍认识,由于男俊女美且三观相符,很快两人就看对眼坠入爱河了,但是奈何工作地点不在一起,不得不异地。这刚认识还处于暧昧期的俩年轻人咋能忍住不联系呢。于是互相交换了手机号加上了wx,相亲结束后,每日通过手机互相联系,增进感情,不日,便确定关系,订婚,结婚,买房,生娃......停停停,给我回来。

咳咳咳,故事呢,其实到 "每日通过手机互相联系" 就结束了哈,后面自行脑补。在上面这则小故事中,媒人就是主进程,渲染进程一和二在最初,会通过主进程进行一个交换 port 的过程,后续都通过 port 来进行通信,不再依赖主进程了。

乍一看,是不是觉得这种通信方式比前面介绍的那些靠谱多了,而且还不需要通过主进程中继的性能开销。

讲完了故事,聊了个大概,让我们来看看本篇文章大纲吧:

  • MessagePort 的基础用法

  • 主进程与渲染进程通信案例分析

  • 渲染进程与渲染进程案例预告

image.png

1. MessagePort 的基础用法

1.1 如何创建 MessagePort

首先还是得先来看看 MessagePort 的基础用法。MessagePort 对象的创建依赖于 MessageChannel 类:

const channel = new MessageChannel();
const port1 = channel.port1
const port2 = channel.port2// 或者简写为:
const { port1, port2 } = new MessageChannel();

实例化 MessageChannel 类之后,就产生了两个 portport1 和 port2 。这两个 port 就是 MessagePort 对象。它就是我们上面那则故事提到的,可以用于两个进程之间进行长期通信的关键所在。

举个小例子,假设现在:

  • 渲染进程一有了 port1

  • 渲染进程二有了 port2

那么现在这两个进程就可以通过 port.onmessageport.postMessage 来收发彼此间的消息了:

// 渲染进程一:
port1.onmessage = (event) => {console.log('received result:', event.data)
};
port1.postMessage('我是渲染进程一发送的消息');// 渲染进程二:
port2.onmessage = (event) => {console.log('received result:', event.data)
};
port2.postMessage('我是渲染进程二发送的消息');

只要 port1port2 一直都存在,它们就可以进行持久通信,怎么样,是不是很 niubility

OKK,那么现在如果是在渲染进程一创建的这两个 port ,关键就是如何把 port2 给到另一个渲染进程二了。也就涉及到了 MessagePort 的传递。

image.png

1.2 ipcRenderer.postMessage()

说到 MessagePort 的传递就得谈到 ipcRenderer 对象的 postMessage 方法了。因为 MessagePort 对象就是依靠它来传递。没错,此时应该有小伙伴可能想起来了,我们平常网页上的 window 对象也有一个 postMessage 方法,这两者之间其实挺像的,只不过呢,是在不同的通道上。

portMessage 它的参数如下:

ipcRenderer.postMessage(channle, message, [transfer])

  • channel String:事件名

  • message any:要传递的消息

  • transfer MessagePort[] (optional):0个或多个 MessagePort 对象。

前两个好理解,其实和 ipcRenderer 的其它方法差不多,事件,以及传递的消息。第三个参数有些特别,它是一个数组,其中可以传递 MessagePort 对象。这里需要注意,别看第三个参数标记的是 optional ,但其实它也是需要传递的,如果你不需要传 MessagePort 对象,那么就需要定义一个空数组,否则就会报错啦。

另外,在之前的文章中,我们还有用到 ipcRenderer 的其它方法: sendinvokesendSync ,这三种方法主进程都是可以给渲染进程传递返回结果的,比如:

//  render.js
const replyMessage = await ipcRenderer.invoke('render-invoke-to-main', '我是渲染进程通过 invoke 发送的消息');
console.log('replyMessage', replyMessage); // "我是主进程返回的消息"

postMessage 的第二个参数也可以发送消息,那它是否也可以当成 send 或者 invoke 来用呢?这里我测试了一下,发现主进程那边不论是用 event.reply 还是用 event.returnValue 都不行,看来,官方还是希望我们遵循:”什么样的API就做什么样的事” ,而 ipcRenderer.postMessage ,他的主要职责就是用来发送 MessagePort 的。

并且!ipcRenderer.postMessage 只能通过 ipcMain.on 来接收到, ipcRenderer.on 是接收不到的!

这样的话,看来如果我们要将某个 port 从一个渲染进程给到另一个渲染进程还是得依靠主进程了,需要它这个 媒人 来从中做媒。但问题不大,一旦这两人连接上了,就不再需要媒人了。

同时我们发现,通过这种方式我们也可以实现渲染进程与主进程之间的互相通信了,主进程在收到 port 的时候,如果不给其他人,自己用来和渲染进程通信也可以呀。

image.png

2. 主进程与渲染进程通信案例分析

好嘞,扯了这么多,让我们先写个小 demo,来看看通过 MessagePort 主进程与渲染进程是如何通信的吧。

和之前一样,让我们确定下要做什么事:

  • 在某个时机,渲染进程创建了两个 port 并将其中一个(名为 port1)发送给了主进程

  • 渲染进程这边的另一个 port2 绑定监听事件

  • 主进程接收到 port1 并将它保存下来,同时也绑定监听事件

  • 在另一个时机渲染进程通过 port2 给主进程发送消息

下面是 demo 的时序图:

image.png

第一步、调整目录结构

由于这个案例说的是渲染进程与主进程的通信,让我们基于之前的分支 example-3 再新建一个 example-4,同时删除我们不用的窗口2,此时目录结构变为:

(example-4: https://github.com/LinDaiDai/electron-ipc-example/tree/example-4)

image.png

第二步、渲染进程提供生成 MessagePort 并发送给主进程的能力

之前提到了,做的第一件事:

  • 在某个时机,渲染进程创建了两个 port 并将其中一个(名为 port1)发送给了主进程

这里的某个时机,我们就在页面上定义两个按钮吧:

  1. 点第一个按钮创建并发送 port

  2. 点第二个按钮给主进程发送消息

// window-one/index.html
<body><h1>Window One</h1><button onclick="sendPortToMain()">窗口1 postMessage 给主进程发送消息端口 port1</button><button onclick="sendMessageToMain()">窗口1 通过 port2 给主进程发送消息</button><script src="./renderer.js"></script>
</body>

对应的渲染进程的代码:

// window-one/render.js
const { ipcRenderer } = require('electron')let portToMainfunction sendPortToMain() {// 1、创建一对 portconst { port1, port2 } = new MessageChannel()// 2、给主进程传输消息端口 por1ipcRenderer.postMessage('render-post-message-to-main','我是渲染进程一通过 ipcRenderer.postMessage 发送过来的',[port1],)// 3、把 port2 赋值给 portToMain,方便其他模块获取portToMain = port2// 4、port2 绑定事件监听,之后主进程发送的消息都会在这里接收到portToMain.onmessage = (event) => {const data = event.dataconsole.log('[Renderer receive]message', data)}
}function sendMessageToMain() {portToMain.postMessage('我是渲染进程一通过传声筒 port 发送过来的')
}

在上面代码中,点击第一个按钮执行 sendPortToMain 方法,其中创建了一堆 port ,并将其中一个通过 ipcRenderer.postMessage 发送给了主进程,同时设置监听。

点击第二个按钮,到时候会执行 sendMessageToMain 方法,就可以利用 port 进行通信了。

第三步、主进程提供接收 port 和设置监听的能力

在第二步中,渲染进程发送了 port 给主进程,那么主进程这边肯定要设置一个地方去接收,接收后同时也要保证它和渲染进程后续能持续通信。

那么只需要如下处理:

// main/ipc.js
const { ipcMain } = require('electron')// 1、主进程监听一个事件,渲染进程想要发送 port 的话,就能在这里获取到
ipcMain.on('render-post-message-to-main', (event, params) => {console.log('[Main receive]render-post-message-to-main', params)// 2、获取到 port1const port1 = event.ports[0]// 3、需要调用一下 port1 的 start()port1.start()// 4、port1 绑定事件监听,之后渲染进程一发送的消息都会在这里接收到port1.on('message', (event) => {const data = event.dataconsole.log('[Main receive]message', data)port1.postMessage('我是主进程通过 port 回复的消息')})
})

(记得将 main/ipc.js 在主进程中引用一下哦)

// main/index.js
const ipc = require('./ipc')// ...其他代码

在上面的代码中,我们先用 ipcMain 保证能接收到渲染进程发送过来的 port ,再调用 port1.start() ,然后给它绑定 message 事件,之后渲染进程一发送过来消息都能接收到,也能通过 port1 给渲染进程一发。

第四步、效果演示

一切代码准备就绪,让我们启动项目来看看效果。

分别点击窗口中的第一个和第二个按钮,能够看到主进程和渲染进程的打印日志:

image.png

(终端里主进程的打印中文会乱码,还请理解…)

image.png

3. 渲染进程与渲染进程案例预告

在看完了上面的案例之后,相信你对于这种用 postMessage 进行窗口间通信的方式有了一些了解。实际的开发场景中,我们可能还会进行渲染进程与渲染进程间的通信,甚至是同一个进程内部之间的通信。在后面的文章中,我们会介绍如何通过 postMessage 来实现一个比较通用的 electron ipc 通信的库,你也可以先利用上面的知识自己尝试着看看可以如何去写,敬请期待哦。

后语

这篇文章就介绍到这里。通过这三个章节的介绍,相信你对 ipc 大致的通信都有所了解了吧。希望在实际的开发中能够帮助到你。

喜欢「霖呆呆」的小伙还希望可以关注霖呆呆的公众号 LinDaiDai

我会不定时的更新一些前端方面的知识内容以及自己的原创文章

大概是全网最详细的Electron ipc 讲解(三)——定情信物传声筒port相关推荐

  1. 大概是全网最详细的Electron ipc 讲解(二)——渲染进程与渲染进程的搭桥牵线

    希沃ENOW大前端 公司官网:CVTE(广州视源股份)[1] 团队:CVTE旗下未来教育希沃软件平台中心enow团队 「本文作者:」 image.png 前言 你盼世界,我盼望你无 bug .Hell ...

  2. 大概是全网最详细的Electron ipc 讲解(一)——主进程与渲染进程的两情相悦

    希沃ENOW大前端 公司官网:CVTE(广州视源股份) 团队:CVTE旗下未来教育希沃软件平台中心enow团队 「本文作者:」 image.png 前言 你盼世界,我盼望你无 bug .Hello 大 ...

  3. 大概是全网最详细的何恺明团队顶作MoCo系列解读...(完结篇)

    ​作者丨科技猛兽 编辑丨极市平台 本文原创首发于极市平台,转载请获得授权并标明出处. 大概是全网最详细的何恺明团队顶作 MoCo 系列解读!(上) 本文目录 1 MoCo v2 1.1 MoCo v2 ...

  4. 【深度学习】大概是全网最详细的何恺明团队顶作MoCo系列解读...(完结篇)

    作者丨科技猛兽 编辑丨极市平台 导读 kaiming 的 MoCo让自监督学习成为深度学习热门之一, Yann Lecun也在 AAAI 上讲 Self-Supervised Learning 是未来 ...

  5. Attention 和 Self-Attention [一万字拆解 Attention,全网最详细的注意力机制讲解]

    上一篇文章 从 RNN 到 Attention 我们在RNN的Encoder-Decoder框架下引入了Attention 机制,用来解决 RNN 模型中梯度下降以及性能瓶颈问题,如下图所示: 上图就 ...

  6. “是男人就下一百层”h5游戏全网最详细教学、全代码,js操作

    "是男人就下一百层"h5游戏全网最详细教学.全代码,js操作 博主的话 游戏展示 编程工具介绍 游戏代码 代码讲解 js 第一步 切换div的显示与隐藏 js 第二步 在菜单页面用 ...

  7. 最新阿里大于短信配置接口-2020全网最详细版-划水小老虎

    最新阿里大于短信配置接口-全网最详细版 一,登录阿里云,做对接前准备 1,配置签名 2,配置模板 3,配置acessKey 二,下载阿里大于的SDK 三,发送短信 1,解压文件,放入TP5框架中 2, ...

  8. 全网最详细的Windows里Anaconda-Navigator启动后闪退的解决方案(图文详解)

    全网最详细的Windows里Anaconda-Navigator启动后闪退的解决方案(图文详解) 参考文章: (1)全网最详细的Windows里Anaconda-Navigator启动后闪退的解决方案 ...

  9. 全网最详细的大数据集群环境下如何正确安装并配置多个不同版本的Cloudera Hue(图文详解)...

    不多说,直接上干货! 为什么要写这么一篇博文呢? 是因为啊,对于Hue不同版本之间,其实,差异还是相对来说有点大的,具体,大家在使用的时候亲身体会就知道了,比如一些提示和界面. 全网最详细的大数据集群 ...

最新文章

  1. sobel算子_OpenCV 学习:4 Sobel算子
  2. howdoi 简单分析
  3. ODBG常用快捷键总结
  4. 每天一个实用小技巧!归纳多个文件、批量修改文件名
  5. 指令重排序导致的可见性问题
  6. CSS完美实现垂直居中-测试页
  7. HanLP: Han Language Processing
  8. python正弦波叠加方波_电赛初探(一)——正弦波、方波、锯齿波转换
  9. Text to Image 文本生成图像定量评价指标分析笔记 Metric Value总结 IS、FID、R-prec等
  10. springboot2.x 整合 elasticsearch 创建索引的方式
  11. linux 打印文件目录结构,linux基本文件目录的结构及管理
  12. 我用java写了个壁纸软件
  13. 如何利用宝塔面板+JavaWeb+MySQL设计一个注册登录界面
  14. 驾驶员理论考试通过!
  15. Linux环境搭建基础(二)
  16. Git详解之六:Git工具
  17. 中继 并发量_2E1数字中继网关支持60并发
  18. 基于java的物流信息管理系统(计算机毕业设计)
  19. 如何给客户进行价值塑造?说一万句话,不如讲一个故事
  20. BUAA(2021春)实验:树的构造与遍历——根据提示循序渐进(可惜提示有问题Ծ‸Ծ)

热门文章

  1. 几种主流快速开发平台选择
  2. 实现在 .net 中使用 HttpClient 下载文件时显示进度
  3. Android 10.0 蓝牙去掉传输文件的功能
  4. MySQL学习笔记-基础篇1
  5. IPsec IKE第一阶段主模式和野蛮模式
  6. 手机屏幕xy坐标软件_软件工程中的xy问题
  7. SQLServer2008R2安装和使用
  8. 任务栏信息栏中图标闪动
  9. 【图像处理】基于matlab边缘检测 Sobel、Roberts、Prewitt
  10. FPV救援四足机器人设计(1)