Electron进程间通信

Electron桌面应用中有两个进程,分别是Main主进程和Renderer渲染进程。两个进程间有多种方法进行通信。

一、主进程和渲染进程

1、主进程Main

main.js在启动应用后就创建了一个主进程main process,它可以通过electron中的一些模块直接与原生GUI(在你的应用窗口)交互。

2、渲染进程Renderer

仅启动主进程并不能给你的应用创建应用窗口。窗口是通过main文件里的主进程调用叫BrowserWindow的模块创建的。每个页面都是运行在自己的进程里,这些进程我们称之为渲染进程。渲染进程会在窗口中渲染出web页面(引用了CSS,JavaScript,图片等的HTML文件)。web页面是Chromium渲染的,因为各系统下标准是统一的的,所以兼容性很好。

3、主进程于渲染进程的关系

主进程通过构造BrowserWindow实例来创建页面。每个 BrowserWindow实例都在自己的渲染进程里运行页面。当一个 BrowserWindow 实例被销毁后,相应的渲染进程也会被终止。
主进程管理所有页面和与之对应的渲染进程。每个渲染进程都是相互隔离的,并且只知道运行在该进程里的页面。
在页面里调用本地GUI是不允许的,因为在Web页面里管理本地GUI资源是非常危险而且容易造成资源泄露。如果你想在网页里进行GUI操作,该页面的渲染进程必须与主进程进行通讯,请求主进程进行相关的 GUI 操作。

二、几种通信方式

1、ipc模块

  • ipcMain模块
  • ipcRenderer模块
    ipcMain模块和ipcRenderer是类EventEmitter的实例。
    在Electron项目中,使用require来引入这个模块,而在Electron-vue中,由于使用了webpack,可以使用import引入。
1.1、ipcMain

监听 channel,当接收到新的消息时 listener 会以 listener(event, args...) 的形式被调用。

添加一次性的 listener。当且仅当下一个消息发送到 channel 时 listener 才会被调用,随后listener会被移除。

从监听器数组中移除监听 channel 的指定 listener。

删除所有监听者,或特指的 channel 的所有监听者。

1.2、ipcRenderer

监听 channel, 当新消息到达,将通过 listener(event, args...) 调用 listener

通过 channel 发送异步消息到主进程,可以携带任意参数。 在内部,参数会被序列化为 JSON,因此参数对象上的函数和原型链不会被发送。
主进程可以使用 ipcMain 监听channel来接收这些消息。

  • ipcRenderer.sendSync(channel[, arg1][, arg2][, ...])

通过 channel 发送同步消息到主进程,可以携带任意参数。 在内部,参数会被序列化为 JSON,因此参数对象上的函数和原型链不会被发送。

主进程可以使用 ipcMain 监听channel来接收这些消息,并通过 event.returnValue设置回复消息。

  • ipcRenderer.sendTo(webContentsId, channel, [, arg1][, arg2][, ...])

通过channel向具有WebContentSid的窗口发送消息

  • ipcRenderer.sendToHost(channel[, arg1][, arg2][, ...])

就像 ipcRenderer.send,不同的是消息会被发送到 host 页面上的 <webview> 元素,而不是主进程。

1.3、Renderer进程向Main进程发送消息,Main进程进行回复(ipc模块没有Main进程向Renderer模块发送的方法)

  • 发送消息时,事件名称为channel(如例子中的asynchronous-message)
1.3.1、异步消息
  • 主进程将异步消息发送回发件人,需要使用event.sender.send(...)
// Renderer进程(为Vue页面或main.js页面)
import {ipcRenderer} from 'electron';
import Vue from 'vue';

<template>
  <div>{{this.msg}}</div>
</template>

<script>
ipcRender.on('asynchronous-reply', function (event, arg) { // 接收到Main进程返回的消息
  const message = `异步消息回复: ${arg}`
})
export default{
  mounted(){
   ipcRenderer.send('asynchronous-message', 'ping') //给主进程发送消息“ping”
  }
}
//Main进程(为js文件)
import {ipcMain} from 'electron';

ipcMain.on('asynchronous-message',(event, arg) => { // arg为接受到的消息
  event.sender.send('asynchronous-reply', 'pong'); // 返回一个'pong'
})
1.3.2、同步消息

可以使用ipc 模块在进程之间发送同步消息. 但请注意, 此方法的同步特性意味着它在完成任务时会阻止其他操作

  • 主进程回复同步信息时,需要设置event.returnValue
// Renderer进程
import {ipcRenderer} from 'electron';
import Vue from 'vue';

<template>
  <div>{{this.msg}}</div>
</template>

<script>
ipcRender.on('synchronous-reply', function (event, arg) { // 接收到Main进程返回的消息
  const message = `异步消息回复: ${arg}`
})
export default{
  mounted(){
   ipcRenderer.sendSync('synchronous-message', 'ping') //给主进程发送消息“ping”
  }
}
//Main进程
mport {ipcMain} from 'electron';

ipcMain.on('synchronous-message',(event, arg) => { // arg为接受到的消息
  event.returnValue = 'pong' // 返回一个'pong'
})

2、webContents.send方法(Main进程主动向Renderer进程发送消息)

webContents.sendBrowserWindow类的一个方法,BrowserWindow类用于创建一个程序窗口,实例化之后,设置窗口宽高,并设置其loadURL(加载的页面),一个窗口就创建成功并开始显示。通信方法如下

mainWindow.webContents.send('list', res.data);
// mainWindow是一个BrowserWindow实例

在渲染进程中,依旧是使用ipcRenderer对消息进行接收

ipcRenderer.on('list', (e, msg) => {
  console.log(msg);
  });
}

3、remote模块

remote模块支持RPC风格的通信,在渲染进程中获取主进程创建的一些全局对象和应用信息,还可以调用主进程所提供的一些方法,如重启应用、操作渲染进程等。
在Electron中, GUI 相关的模块 (如 dialogmenu 等) 仅在主进程中可用, 在渲染进程中不可用。 为了在渲染进程中使用它们, 必须使用 remote 模块,。你可以调用 main 进程对象的方法, 而不必显式发送进程间消息, 类似于 Java 的 RMI 。

  • 从渲染进程创建浏览器窗口的一个例子
const { BrowserWindow } = require('electron').remote;
let win = new BrowserWindow({ width: 800, height: 600 });
win.loadURL('https://github.com');

注意: 反向操作( 从主进程访问渲染进程) ,可以使用webContents.executeJavascript

3.1远程对象

remote 模块返回的每个对象 (包括函数) 表示主进程中的一个对象 (我们称它为远程对象或远程函数)。 当调用远程对象的方法时, 调用远程函数, 或者使用远程构造函数 (函数) 创建新对象时, 实际上是在发送同步进程消息。
在上面的示例中, BrowserWindowwin (browser-window. md) 都是远程对象, new BrowserWindow 在渲染过程中没有创建 BrowserWindow 对象。 取而代之的是,它在主进程中创建了一个 BrowserWindow对象,并且在渲染进程中返回相应的远程对象,即win对象。
请注意只有可枚举属性才能通过 remote 进行访问。

3.2远程对象的生命周期

Electron 确保在渲染进程中的远程对象存在(换句话说,没有被垃圾收集),那主进程中的对应对象也不会被释放。当远程对象被垃圾收集之后,主进程中的对应对象才会被取消关联。如果远程对象在渲染进程泄露了(即,存在某个表中但永远不会释放),那么主进程中的对应对象也一样会泄露,所以你必须小心不要泄露了远程对象。
但是,字符串和数字等主要值的类型是通过复制发送的。

3.3给主进程传递回调函数

在主进程中的代码可以从渲染进程——remote模块——中接受回调函数,但是使用这个功能的时候必须非常非常小心。
首先,为了避免死锁,传递给主进程的回调函数会进行异步调用。所以不能期望主进程来获得传递过去的回调函数的返回值。
其次,传递给主进程的回调将持续到主进程垃圾回收。主进程会一直保持对这个回调函数的引用,除非明确的卸载它。如果不卸载,每次重新载入窗口都会再次绑定,这样每次重启就会泄露一个回调函数。为了避免这个问题,请确保清除对传递给主进程的渲染器回调的引用。 这涉及到清理事件处理程序, 或者确保主进程被明确告知取消引用来自正在退出的渲染程序的回调。

3.4访问主进程中的内置模块

主过程中的内置模块被添加为 remote 模块中的获取器,因此可以像 electron 模块一样直接使用它们

const app = require('electron').remote.app
console.log(app)
3.5remote的几个方法及属性

返回主进程中require(module) 返回的对象。 由其相对路径指定的模块将相对于主进程的入口点来解析。

返回 BrowserWindow 即此网页所属的窗口

返回 WebContents 即此网页的 web 内容

返回主进程中 name (例如 global[name]) 的全局变量。

主进程中的 process 对象。这与 remote.getGlobal('process') 相同, 但已被缓存。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容

  • 患有乙肝的妈妈请注意。对乙肝表面抗原阳性母亲的新生儿,应在出生后24小时内尽早注射乙型肝炎免疫球蛋白,同时在不同部...
    简单明了阅读 304评论 0 0
  • 我感冒了,自己一个人躺在床上看书,做自己喜欢的事时会缓解难受,如果我不舒服就会看电影,看书,做手工,把注意力转移。...
    水木的小院阅读 456评论 0 3
  • 调查显示,在中国,有9.5%的女童和8%的男童都曾遭到过不同方式的性侵害,总数高达2500万人,而且多数都是...
    龠瀹阅读 990评论 0 0
  • 突然想消失 因为自己的努力不够 因为爱的人照顾不了 因为所有关系都弄得一团糟 因为什么都不好 所以累了 想消失不见
    蜘蛛侠和白雪公主阅读 192评论 0 0