主要目的
- 簡(jiǎn)化主進(jìn)程與渲染進(jìn)程的通信,統(tǒng)一寫(xiě)法
- 支持跨端打包秘通,適配原生方法的寫(xiě)法伟端,render中無(wú)需判斷當(dāng)前環(huán)境
調(diào)用主進(jìn)程
1. 渲染進(jìn)程
向主進(jìn)程發(fā)送信息調(diào)用函數(shù),需要傳遞我們要調(diào)用的方法名澡绩,參數(shù),以及一個(gè)接收返回值的回調(diào)函數(shù).為了方便調(diào)用我們掛在全局對(duì)象Window上
基本結(jié)構(gòu):window.hybridBridge = (bridgeName, data, callback) { }
但是這樣還是不夠的俺附,需要一個(gè)處理回調(diào)事件的中心肥卡,因此引入一個(gè)回調(diào)對(duì)象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) //保存回調(diào)
electron.ipcRenderer.send('postMessage', msg) //向主進(jìn)程發(fā)送消息
}
2. 主進(jìn)程
主進(jìn)程我們要監(jiān)聽(tīng)渲染進(jìn)程的消息進(jìn)行相關(guān)調(diào)用,主要就是用ipcMain來(lái)監(jiān)聽(tīng)
function initBridge(){
ipcMain.on('postMessage', async (event: Electron.IpcMainEvent, msg: bridgeMessgae) => {
}
}
- 各模塊進(jìn)行區(qū)分(可選):例如下結(jié)構(gòu)將函數(shù)寫(xiě)在各個(gè)模塊中事镣,函數(shù)第一個(gè)接收參數(shù)步鉴,第二個(gè)為回調(diào)
common.ts
/*
文件結(jié)構(gòu)
-- src
-- bridege
-- index.ts
-- common
-- module1
-- module2
*/
function doSometings(_params: any, callback: (res: Record<string, unknown>) => void)){
const {} = _params
...
callback({
code: 1 | -1 ,
...
})
}
- 獲取函數(shù)名和參數(shù)進(jìn)行調(diào)用,通過(guò)bridgeName調(diào)用通用模塊
import eventHandles from '@/bridge/index' //引入main進(jìn)程函數(shù)處理Handle
ipcMain.on('postMessage', async (event: Electron.IpcMainEvent, msg: bridgeMessgae) => {
const names = msg.bridgeName.split('/')
//結(jié)果處理函數(shù)
const senderHandler = (data: Record<string, unknown>)=>{
//檢查主窗口
if (!global.__mainWindow) {
return
}
//封裝下給render的數(shù)據(jù)
let sendermsg = {
bridgeName: message.bridgeName,
cid: message.cid,
data,
}
// 發(fā)送給render....
}
//通用模塊調(diào)用
if(name.length === 1) {
eventHandles[names[0]](msg.data,senderHandler)
}
//調(diào)用其他模塊,例如 moudle/geName
try {
eventHandles[names[0]][names[1]](msg.data,senderHandler) //執(zhí)行函數(shù)
} catch (err) {
}
}
渲染進(jìn)程接收結(jié)果
1.主進(jìn)程
上面剛接收到渲染進(jìn)程后調(diào)用函數(shù)執(zhí)行后,在處理函數(shù)senderHandler中將結(jié)果封裝氛琢,接下來(lái)通過(guò)ipcMain將數(shù)據(jù)返回.
function initBridge(){
ipcMain.on('postMessage', async (event: Electron.IpcMainEvent, msg: bridgeMessgae) => {
//1.接收參數(shù)msg , 校驗(yàn)
...
//2.調(diào)用函數(shù)喊递,回調(diào)接收處理結(jié)果
//3.發(fā)送給render進(jìn)程
const senderHandler = (data: Record<string, unknown>)=>{
//檢查主窗口
//封裝下給render的數(shù)據(jù)
let sendermsg = { ... }
// 發(fā)送給render
if (event.sender.isDestroyed()) {
return;
}
event.sender.send('receiveMessage', {
bridgeName: message.bridgeName,
cid: message.cid,
data,
})
}
}
}
2.渲染進(jìn)程
主進(jìn)程接發(fā)送參數(shù)后,渲染進(jìn)程使用Ipcrender監(jiān)聽(tīng)接收
electron.ipcRenderer.on('receiveMessage', (_: any, message: bridgeMessgae) => {
const { data, cid, error } = message
// 如果存在方法名阳似,則調(diào)用對(duì)應(yīng)函數(shù)
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')
}
})