前言

如果你是一个Electron的web桌面开发者,又想简化IPC通信开发,推荐你上手体验这个框架。装饰器、自动扫描、性能优化,让你开发更高效和专注,进阶到全新的Electron主进程和渲染进程通信高度。


一、是什么?

这是一个用于在Electron的主进程和渲染进程之间进行IPC通信的框架。它具有以下功能:

在渲染进程中

  • 使用@ipc装饰器可以方便地发起对主进程方法的远程调用。
  • IPCProxy类实现了与主进程通信的接口,并在内部使用@ipc装饰器发起远程调用。

在主进程中

  • 使用@IpcMapping装饰器可以给类添加IpcMapping元数据,指定这个类所在的IPC通信group。
  • IPCManager类用于注册IPC通信监听和处理程序。
  • 有一个自动扫描机制,会扫描所有的*.ipc.ts文件,找到@IpcMapping装饰过的类,并自动注册这个类的所有方法作为IPC通信的处理程序。

二、使用步骤

举个例子,有一个UserQuery接口和实现:

类图如下

通过@ipc远程调用
UserQueryIpc
<> IUserQuery
selectById(id: string)
UserQueryProxy
<> IUserQuery
selectById(id: string)
IUserQuery

代码如下

interface IUserQuery {
  selectById(id: string): Promise<string>
} 

@IpcMapping("IUserQuery")
class UserQueryIpc implements IUserQuery {
  selectById(id: string) { ... }
}

然后在渲染进程中,可以这样使用:

class UserQueryProxy implements IUserQuery {
  @ipc("IUserQuery")
  selectById(id: string) { ... } 
}

const userQuery = new UserQueryProxy()
userQuery.selectById("1").then(res => { ... })

这个调用会远程调到主进程的UserQueryIpc.selectById方法。
所以通过这个框架,主进程和渲染进程之间的IPC通信变得非常简单,类似本地方法调用的体验。开发者只需要关注业务逻辑,通信细节被框架封装起来。

三、实现细节

渲染进程

在渲染进程中,有两个主要的功能:

  1. @ipc 装饰器,用于发起对主进程方法的远程调用。
export function ipc(group: string) {
  return (target: any, name: string, descriptor: PropertyDescriptor) => {
    descriptor.value = function(...args: any[]) {
      return ipcRenderer.invoke(group + ":" + name, ...args)
    }
  }
}

这个装饰器会拦截被装饰的方法,并在调用时使用ipcRenderer.invoke发起远程调用到主进程。

  1. IPCProxy 类,实现与主进程通信的接口,内部使用@ipc装饰器发起远程调用。
export class UserQueryProxy implements IUserQuery {
  @ipc("IUserQuery")
  selectById(id: string) { ... }
}

这样一来,在渲染进程使用UserQueryProxy,调用selectById方法,实际会远程调用主进程的实现。

主进程

在主进程中,功能更加丰富:

  1. @IpcMapping 装饰器,给类添加元数据,指定这个类所在的IPC通信group
@IpcMapping("IUserQuery")
export default class UserQueryIpc implements IUserQuery {
  ...
}

设计这个group的存在主要是为了防重,这个案例中使用了接口名称,当然也可以定义为其他值

  1. IPCManager 类,用于注册IPC监听和处理程序。
class IPCManager {
  on(channel: string, callback: (...args: any[]) => void) { ... }
  handle(channel: string, callback: (...args: any[]) => Promise<any>) { ... } 
}
  1. 自动扫描机制,会扫描所有的*.ipc.ts文件,找到@IpcMapping装饰过的类,并自动注册这个类的方法作为处理程序。
const ipcMappings = import.meta.globEager("../*.ipc.ts");
for (let ipcMappingsKey in ipcMappings) {
  const IpcClass = ipcMappings[ipcMappingsKey].default;
  const IpcMappingArgs = getDecorator(IpcClass, "IpcMapping"); 
  Reflect.ownKeys(IpcClass.prototype) 
    .filter(key => key !== "constructor")
    .forEach(key => {
      useIPCManager.handle(`${IpcMappingArgs[0]}:${key}`, IpcClass.prototype[key]);
    });
}

这样,UserQueryIpc 类的方法就自动成为了 IPC 通信的处理程序,等待渲染进程的调用。


因为篇幅原因,代码未全部上传文章,如需这个ipc框架的全部代码,请在下方留言

总结

总之,这个IPC通信框架已经实现了基本功能,但要成为一个生产可用的框架,还需要不断完善和优化。这也是一个不断积累和提高的过程,需要在实践中不断总结和改进。

Logo

鸿蒙生态一站式服务平台。

更多推荐