首頁 > 軟體

Electron程序間通訊的實現

2022-05-24 14:00:32

使用Electron開發出來的桌面應用都是多程序的,其中包含了一個主程序(Main)和至少一個渲染程序(Renderer)。

主程序控制整個應用的生命週期,通過electron中的一些模組與GUI互動,同時控制每一個渲染程序。

渲染程序會在BrowserWindow物件建立出的視窗中渲染出Web頁面,每個渲染頁面都執行在獨立的程序中。

主程序與渲染程序之間通訊

ipc模組 + window.webContents

ipc模組包含ipcMain和 ipcRenderer兩個模組,其中ipcMain在主程序中使用,ipcRenderer在渲染程序中使用,在使用之前,要使用require引入對應的模組。

ipc模組中的方法:

  • ipcMain.on(msg, () => {}):監聽渲染程序傳送的msg訊息,並做出響應。
  • ipcMain.once(msg, () => {}):監聽渲染程序傳送的msg訊息,並做出響應,但是監聽到一次msg事件後自動移除這個監聽器。
  • ipcRenderer.on(msg, () => {}):監聽主程序傳送的msg訊息,並做出響應。
  • ipcRenderer.once(msg, () => {}):監聽主程序傳送的msg訊息,並做出響應,但是監聽到一次msg事件後自動移除這個監聽器。
  • ipcRenderer.send(msg, data):監聽渲染程序向主程序傳送msg非同步訊息,並攜帶引數data。
  • ipcRenderer.sendSync(msg, data):監聽渲染程序向主程序傳送msg同步訊息,並攜帶引數
  • ipcRenderer.sentTo(webContentId, msg, data):監聽渲染程序向具有webContentId的視窗傳送訊息
  • ipcRenderer.sendToHost(msg, data):監聽渲染程序向host頁面上的 <webview> 元素傳送訊息

ipc模組還提供了刪除指定監聽器和刪除所有監聽器的方法:removeListener()、removeAllListener(),這兩個方法在ipcMain和ipcRenderer這兩個模組中的用法是一樣的。

通過上面的幾個監聽器我們發現,單獨使用ipc模組無法實現主程序主動向渲染程序傳送訊息。所以我一般把BrowserWindow範例中的webContents和ipc模組結合使用

一個主程序與渲染程序間通訊的例子

// 在主程序中使用ipcMain
const { ipcMain, BrowserWindow } = require('electron');

window = new BrowserWindow({
    width: 800,
    height: 600
});

// 主程序主動向渲染程序傳送訊息
window.webContents.send('main webContents msg', data);

// 主程序接收渲染程序傳送的訊息,並通過回撥函數做出響應
ipcMain.on('renderer ipc msg', (event, arg) => {
    // TODO something
})
// 在渲染程序中使用ipcRender
const ipcRender = require('electron');

// 渲染程序中使用ipcRenderer.on接收主程序訊息,並通過回撥函數做出相應
ipcRenderer.on('main webContents msg', (event, arg) => {
    // 在相應主程序事件時,通過ipcRenderer.send方法像主程序傳送另一條訊息
    ipcRenderer.send('renderer ipc msg', data);
})

ipcRenderer傳送的同步訊息和非同步訊息

在上面列舉的幾個方法中,其中ipcRenderer傳送訊息的方法分為傳送同步訊息的方法ipcRenderer.send和傳送非同步訊息的方法ipcRenderer.sendSync。主程式在監聽到這兩種不同方法的訊息時,可以通過不同的方式給渲染程序返回訊息:

// 渲染程序

// 渲染程序傳送非同步訊息
ipcRenderer.send('msg', data);

// 渲染程序傳送同步訊息。 傳送同步訊息,任務未完成時會阻止其他操作
var message = ipcRenderer.sendSync('sync msg', data);
ipcMain.on('msg', (event, arg) => {
    // 主程序監聽到渲染程序發的非同步訊息後,通過event.sender.send()的方式進行響應,可以在渲染程序中使用ipcRenderer.on監聽'return msg'訊息
    event.sender.send('return msg', data)
})

ipcMain.on('sync msg', (event, arg) => {
    event.retuenValue = 'msg';
})

remote模組

在渲染程序中使用remote,可以呼叫主程序所提供的一些方法。(例如:dialog、menu等模組)

const { BrowserWindow } = require('electron').remote;

//通過remote模組,可以在渲染程序中呼叫BrowserWindow模組
let win = new BrowserWindow({ width: 800, height: 600});
win.loadURL('index.html');

渲染程序中使用remote模組返回的物件,都代表了主程序中的一個物件,一般稱為遠端物件。呼叫遠端物件的方法時,實際上是在想主程序傳送同步訊息。

比如上面的程式碼中,BrowserWindow範例是通過remote模組返回的,所以渲染程序中的BrowserWindow和win都是遠端物件。在執行new BrowserWindow({...})這段程式碼的時候,並沒有在渲染程序中建立BrowserWindow範例的物件,而是在主程序中建立了BrowserWindow物件,並把這個物件返回到渲染程序中。

remote的方法和屬性

  • remote.require(module):返回主程序中的物件
  • remote.getCurrentWindow():返回此網頁所屬的視窗
  • remote.getGlobal(name):返回主程序中name的全域性變數
  • remote.process:返回主程序中的process物件

渲染程序之間通訊

上面提到的通訊方法,經過測試發現都無法在渲染程序之間直接通訊,有時候我們開發中可以使用主程序作為中轉進行渲染程序間的通訊:

// renderer process A
const { ipcRenderer } = require('electron');
ipcRenderer.send('A send msg', data);
// main process
const { ipcMain, BrowserWindow } = require('electron');

let win = new BrowserWindow({...});

ipcMain.on('A send msg', (event ,arg) => {
    // TODO something
    win.webContents.send('main send msg', data);
})
const { ipcRenderer } = require('electron');
ipcRenderer.on('main send msg', (event, arg) => {
    // TODO something
})

除了上面這種需要main process中轉的方式之外,還有一種方式能夠實現渲染程序之間的直接通訊:

// main process
// 兩個視窗互相獲取對方的視窗 id, 並行送給渲染程序
const { BrowserWindow} = require('electron');

let win1 = new BrowserWindow({...});
let win2 = new BrowserWindow({...});

win1.webContents.send('distributeIds',{
    win2Id : win2.id
});
win2.webContents.send('distributeIds',{
    win1Id : win1.id
});
// renderer process
const { remote } = require('electron').remote;

// fromId() 可以根據視窗id找到目標視窗
remote.BrowserWindow.fromId(win2Id).webContents.send('msg', data);

到此這篇關於Electron程序間通訊的實現的文章就介紹到這了,更多相關Electron程序間通訊內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com