主要目的
- 简化主进程与渲染进程的通信,统一写法
- 支持跨端打包,适配原生方法的写法,render中无需判断当前环境
调用主进程
1. 渲染进程
向主进程发送信息调用函数,需要传递我们要调用的方法名,参数,以及一个接收返回值的回调函数.为了方便调用我们挂在全局对象Window上
基本结构:window.hybridBridge = (bridgeName, data, callback) { }
但是这样还是不够的,需要一个处理回调事件的中心,因此引入一个回调对象obj(或者map集合)保存,并将信息封装
let cid = uuid()
const callbacks = new Map() | {}
type bridgeMessgae {
bridgeName,
data,
...
}
window.hybridBridge = (bridgeName, data, callback) {
msg = {
bridgeName,
data
}
callbacks.set(cid,callback) //保存回调
electron.ipcRenderer.send('postMessage', msg) //向主进程发送消息
}
2. 主进程
主进程我们要监听渲染进程的消息进行相关调用,主要就是用ipcMain来监听
function initBridge(){
ipcMain.on('postMessage', async (event: Electron.IpcMainEvent, msg: bridgeMessgae) => {
}
}
- 各模块进行区分(可选):例如下结构将函数写在各个模块中,函数第一个接收参数,第二个为回调
common.ts
/*
文件结构
-- src
-- bridege
-- index.ts
-- common
-- module1
-- module2
*/
function doSometings(_params: any, callback: (res: Record<string, unknown>) => void)){
const {} = _params
...
callback({
code: 1 | -1 ,
...
})
}
- 获取函数名和参数进行调用,通过bridgeName调用通用模块
import eventHandles from '@/bridge/index' //引入main进程函数处理Handle
ipcMain.on('postMessage', async (event: Electron.IpcMainEvent, msg: bridgeMessgae) => {
const names = msg.bridgeName.split('/')
//结果处理函数
const senderHandler = (data: Record<string, unknown>)=>{
//检查主窗口
if (!global.__mainWindow) {
return
}
//封装下给render的数据
let sendermsg = {
bridgeName: message.bridgeName,
cid: message.cid,
data,
}
// 发送给render....
}
//通用模块调用
if(name.length === 1) {
eventHandles[names[0]](msg.data,senderHandler)
}
//调用其他模块,例如 moudle/geName
try {
eventHandles[names[0]][names[1]](msg.data,senderHandler) //执行函数
} catch (err) {
}
}
渲染进程接收结果
1.主进程
上面刚接收到渲染进程后调用函数执行后,在处理函数senderHandler中将结果封装,接下来通过ipcMain将数据返回.
function initBridge(){
ipcMain.on('postMessage', async (event: Electron.IpcMainEvent, msg: bridgeMessgae) => {
//1.接收参数msg , 校验
...
//2.调用函数,回调接收处理结果
//3.发送给render进程
const senderHandler = (data: Record<string, unknown>)=>{
//检查主窗口
//封装下给render的数据
let sendermsg = { ... }
// 发送给render
if (event.sender.isDestroyed()) {
return;
}
event.sender.send('receiveMessage', {
bridgeName: message.bridgeName,
cid: message.cid,
data,
})
}
}
}
2.渲染进程
主进程接发送参数后,渲染进程使用Ipcrender监听接收
electron.ipcRenderer.on('receiveMessage', (_: any, message: bridgeMessgae) => {
const { data, cid, error } = message
// 如果存在方法名,则调用对应函数
if (typeof cid === 'number' && cid != -1) {
if (typeof error !== 'undefined') {
callbacks[cid](error)
} else if (callbacks[cid]) {
callbacks[cid](data)
} else {
throw new Error('Invalid callback id: ' + JSON.stringify(message))
}
//移除事件
callbacks.delete(id);
}
else if(error){
throw new Error(error.message)
}
else {
throw new Error('message format error')
}
})