Electron 本身提供的进程间通讯的方法比较偏底层,使用起来有些繁琐、不易维护。Electron 中渲染进程和主进程之间的通讯,其实就像传统 web 开发中网页端与服务器的通讯。那么 Electron 中进程间通讯能不能实现像调用 HTTP 请求一样方便呢,答案是肯定的。
以下是一个 HTTP 请求的简单封装:
import { request } from "@/utils/request";const { VITE_HOST } = import.meta.env;// #region 操作密码校验接口export interface ICheckPwdResult { /** * 0:成功,其他:失败 */ code: string; message: string;}export interface ICheckPwdData { /** * 类型:LOCK_SCREEN:锁屏 */ type: string; /** * 密码 */ password: string;}/** * 操作密码校验接口 * /project/2205/interface/api/378926 * @author * * @param {ICheckPwdData} data * @returns */export function checkPwd(data: ICheckPwdData) { return request<ICheckPwdResult>({ url: `${VITE_HOST}/user/operation/pwd/check`, method: "POST", data, });}// #endregion
下面是 Electron 中渲染进程向主进程发送请求的封装:
export const setMaximize = () => { return request({ cmd: "setMaximize", });};export const setMinimize = () => { return request({ cmd: "setMinimize", });};export const closeWindow = () => { return request({ cmd: "closeWindow", });};/** * @description 获取 mac 地址 * @returns */export const getMac = () => { return request<string>({ cmd: "getMac", });};
下面细说如何封装:
Electron 进程间通讯有四种模式:
渲染器进程到主进程(单向)渲染器进程到主进程(双向)主进程到渲染器进程(单向)渲染器进程到渲染器进程更多细节可以查看 进程间通信 | Electron
单向和双向的区别就是:单向的消息发出去之后是没有消息返回的,或者说拿不到返回的消息;双向就是请求发出后可以拿到响应信息,就跟 HTTP 请求一样。
举个例子,页面向主进程发起请求,希望拿到计算机的 mac 地址,主进程通过调用相应的 nodejs api 拿到 mac 地址返回,页面拿到消息结果,这就是双向的。
我并没有用到原生就支持双向的 2 模式,而是使用都是单向的 1、3 模式,通过封装后实现双向的效果。主要是因为 Electron 并不支持主进程到渲染器进程的双向模式,也就是主进程给页面主动发送消息后是无法拿到响应的。为了保持封装后代码的统一性,都使用了单向的模式进行封装。
结合下图以及实际代码调用,说说是如何基于单向的消息模式实现双向通讯的。
/** * @description 获取 mac 地址 * @returns */export const getMac = () => { return request<string>({ cmd: "getMac", });};
const handleGetMac = () => { getMac().then((mac) => { model.mac.value = mac; });};
页面中通过调用getMac
方法获取计算机 mac 地址。
getMac
方法是一个异步方法,渲染进程在调用这个方法发送消息的时候,会生成一个 uuid,然后将 uuid 、cmd 字段、data 数据(这里没有)放到消息体里再发送给主进程。同时会在回调队列里增加两条回调,一条成功回调,一条失败回调,并且使用 uuid 标识,成功回调就是 then 里面的函数,失败回调就是 catch 里的函数。
主进程接收到消息后,根据cmd
字段做相应的处理,处理完后将结果
和渲染进程发送的消息体里的 uuid
放到响应消息体里,响应消息体里也有 cmd
字段,并且是固定(我使用postMessageCallback
标识),这样渲染进程在接收到消息的时候就知道这是一条之前发送出去的消息的响应。响应消息体里还有一个code
字段标识是成功还是失败。
渲染进程接收到消息后,根据消息体里的 cmd
字段判断消息是响应消息(cmd
为postMessageCallback
)还是普通消息(主进程主动发送的消息)。如果是响应消息,根据 uuid
在回调队列里找到相应的回调,再根据 code
判断是执行成功回调还是失败回调。