Electron 通信新思路

这里指主进程与渲染进程之间的通信。

就像官方文档说的那样:Electron Docs -> Best Practices -> Security

  1. Only load secure content
  2. Disable the Node.js integration in all renderers that display remote content
  3. Enable context isolation in all renderers that display remote content

新版本的要求是,渲染进程不再建议开启 nodeIntegrationallowRunningInsecureContent 开关,并且对于外部远程内容,强烈建议打开 sandbox 开关。

那么,对于我们日常开发的本地渲染进程,如何优雅地和主进程之间进行通信,就需要我们去另辟蹊径了。

好在,Electron 虽然关上了一扇窗户,但是又打开了另一扇新的窗户,在 preload 中预加载的 js 环境中,就给我们留下一条后路,因为在预加载 js 里面,require('electron') 是被允许的,而且还提供了一个工具,可以使我们将这个文件里定义好的变量或方法方便地“挪移”到渲染进程的普通 js 环境里去,这个工具就是 —— contextBridge

一段官方示例如下:

// Preload (Isolated World)
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electron', {
  doThing: () => ipcRenderer.send('do-a-thing')
});

在渲染进程里这样使用:

// Renderer (Main World)
window.electron.doThing()

其中,'electron' 只是随便起的名称,并不意味着整个 electron 对象“挪移”到了渲染进程。

问题是,现在,虽然可以在渲染进程里调用 window.electron.doThing() 进行通信了,但是如果我通信的 channel 太多,是不是要一个个地定义 doXXX() 方法?岂不太麻烦了!

改进一:

一种思路是,将 ipcRenderer 对象“挪移”到了渲染进程里,我们试试看

// Preload (Isolated World)
const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electron', {
  ipc: ipcRenderer
});

然后再渲染进程里:

// Renderer (Main World)
console.log(window.electron.ipc);

发现,这里的 ipc ,也有 invoke,有 send,也有 sendSync,就是没有 on,使用这种方式,似乎只能进行 Renderer --> Main 方向的通信,反之则不可以,距离完成我们的任务还有一半距离,如果说项目只需要这单一方向的通信也就罢了,但是如果想要双向通信的话,就要开始新的尝试了。于是有了:

改进二:

我的思路是,既然 contextBridge 不给我暴露 ipcRendereron 方法,那我就自己写一个,于是有了下面的代码:

// Preload (Isolated World)
const { contextBridge: bridge, ipcRenderer: ipc } = require('electron');

bridge.exposeInMainWorld('ipc', {
  send: (channel, data) => ipc.send(channel, data),
  on: (channel, fun) => ipc.on(channel, fun),
});

渲染进程里:

// Renderer (Main World)
console.log(window.ipc);

发现有 sendon 方法,赶快试试:

主进程:

// Main
ipc.on('ping', (e, data) => {
  console.log('received', data);
  setTimeout(() => {
    const count = data + 1;
    e.sender.send('pong', count);
    console.log('sent', count);
  }, 2000);
});

// -->
// received 1
// sent 2

渲染进程:

// Renderer (Main World)
document.addEventListener('DOMContentLoaded', () => {
  const ipc = window.ipc;
  ipc.send('ping', 1);
  ipc.on('pong', (e, data) => {
    console.log('received', data);
  });
});

// -->
// received 2

至此,成功!

完整的例子,参见我的 Github Demo

题外话

Isolated WorldMain World

ELectron 官方把预加载 js 中的环境称为 Isolated World,而把渲染进程中普通 js 中的环境称为 Main World,个人揣测是因为其实现方式,预加载 js 的实现方式其实就是将这个文件当作浏览器插件的形式插入到渲染进程的渲染窗口,所以渲染进程中普通 js 为“主”,预加载 js 为“辅”,有了以上称谓。

文章原发布于《羽痕爱编程》,禁止非本人转载,侵权必究。

### 回答1: electron 是一个开源的跨平台框架,可以用来开发桌面应用程序。它基于 Chromium 和 Node.js,使得使用 web 技术(HTML、CSS 和 JavaScript)开发桌面应用成为可能。 在 electron 中,C 是一种强大且高效的编程语言,常用于为 electron 应用程序编写底层系统级别的功能。C 可以通过 electron 的 addon 机制与 JavaScript 代码进行通信。 通过 electron 的 addon 机制,我们可以将 C 语言中的代码编译成动态链接库(.dll 或者 .so 文件),然后在 JavaScript 代码中调用这些动态链接库中的函数。这样,我们就可以借助 C 语言的能力来处理一些底层的系统任务,比如访问硬件设备、调用操作系统的 API 等。 为了实现 electron C 通信,我们首先需要在 C 语言代码中定义一些函数,这些函数完成特定的功能。然后,通过编写一些 C++ 代码,将这些 C 语言函数封装成 addon,以供 JavaScript 代码调用。最后,我们可以在 JavaScript 代码中通过 require 加载并调用这些 addon,实现与 C 语言的通信。 通过 electron C 通信,我们可以在 electron 应用程序中获得更高的性能和更多的功能。使用 C 语言编写一些底层的功能模块,可以提高程序的效率,并且能够更好地与操作系统进行交互,实现更复杂的功能。因此,electron C 通信为开发者提供了更大的灵活性和功能扩展的可能性。 ### 回答2: electron是一个用于构建跨平台桌面应用程序的开源框架,它结合了Node.js和Chromium,可以使用Web技术(HTML、CSS和JavaScript)来开发桌面应用程序。 在electron中,C语言可以用于编写插件或使用底层操作系统的特殊功能。在electron的主进程中,可以通过Node.js的child_process模块来创建子进程,从而调用C语言编写的可执行文件或动态链接库。通过子进程的标准输入输出,可以与C语言程序进行通信。 通常,在electron中实现与C语言的通信有以下几种方式: 1. 使用子进程通信:在electron的主进程中,可以通过child_process模块启动一个C语言编写的可执行文件,并通过标准输入输出与其进行通信。C语言程序可以通过stdin接收来自electron的数据,并通过stdout返回结果。 2. 使用插件通信electron支持使用C或C++编写插件,这些插件可以通过V8引擎提供的接口与JavaScript进行通信。这种方式需要使用C或C++的桥接代码来实现JavaScript和C语言之间的数据转换。 3. 使用共享内存通信electron主进程和C语言程序可以使用共享内存进行高效的数据传输。通过在两者之间创建共享内存区域,可以直接在内存中读写数据,避免了数据的拷贝和序列化操作。 以上是electron和C语言之间常用的通信方式,具体选择哪种方式取决于应用程序的需求和开发者的技术背景。无论选择哪种方式,都可以实现electron与C语言之间的有效通信,从而结合Web技术和底层功能,开发出功能丰富且高性能的桌面应用程序。 ### 回答3: Electron是一个流行的跨平台应用程序开发框架,它结合了Node.js和Chromium,并允许开发者用Web技术构建桌面应用程序。在Electron中,使用主进程和渲染进程进行通信是非常常见的。 Electron使用IPC(进程间通信)机制来实现主进程和渲染进程之间的通信。IPC提供了几种方法来传递消息和数据: 1. 通过主进程的webContents对象可以向渲染进程发送消息。我们可以使用send()方法发送消息,并使用ipcRenderer.on()方法在渲染进程中监听和处理消息。这种方法可以应用于从主进程向渲染进程发送同步或异步消息,并获取返回结果。 2. 使用Remote模块可以简化主进程与渲染进程之间的通信。通过Remote模块,我们可以在渲染进程中直接调用主进程的模块和方法,就好像它们在同一个进程中一样。这样可以大大简化通信的代码。 3. 使用全局变量或文件来传递数据。主进程和渲染进程可以通过读取和写入共享的全局变量或文件来传递数据。这种方法对于传递较大的数据或复杂的对象可能更合适。 需要注意的是,Electron中的主进程和渲染进程是分开的,它们有不同的运行环境和权限。主进程可以访问底层系统API和资源,而渲染进程则专注于展示用户界面。因此,在进行通信时,我们需要考虑安全性和效率,并选择适合的方法。 总结起来,Electron中的主进程和渲染进程通信可以通过IPC、Remote模块和全局变量/文件来实现。根据实际需求选择合适的方法,可以很方便地在Electron应用中实现功能丰富且可靠的通信机制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值