electron | ipc通信

轉載來自:https://www.cnblogs.com/cc11001100/p/14290450.html

一、主進程和渲染進程

1.1 主進程和渲染進程的概念

在上手ipc通信之前,得對electron的進程模型有個基本的瞭解,electron中的進程大致可以分爲主進程和渲染進程,主進程指的就是nodejs的進程,而渲染進程則可以簡單的理解爲一個Chromium的web頁面。主進程,也就是nodejs進程只有一個,而渲染進程,也就是Chromium的web頁面則可以有多個,ipc通信就是在主進程和渲染進程之間通信。

 

1.2 主進程和渲染進程的環境區別

認爲主進程的代碼是開發者自己寫的,就是普通的node程序,但是渲染進程有可能會加載網頁之類的,可能會執行第三方的js代碼,渲染進程的權限是被限制了的,所以某些敏感操作就需要渲染進程給主進程發消息,讓主進程去做,然後完事了再通知渲染進程。

在使用electron開發客戶端程序的時候,將其類比爲web端的B/S架構,其渲染進程就是前端的頁面,是門面,而主進程則是服務器後臺,負責處理一些與UI無關的業務邏輯,主進程和渲染進程不可避免的要進行一些數據、指令的交換,即這兩個進程之間要通信交換數據,這就是進程間通信,electron提供了ipc模塊用於在主進程和渲染進程之間通信。

 

二、主進程與渲染進程通信

2.1 渲染進程向主進程發送異步消息

渲染進程向主進程發送消息默認就是異步的,在渲染進程的html或者render.js中向主進程發送異步消息:

const electron = require("electron");
// 第一個參數是約定的事件的名稱,主進程要監聽這個事件
// 第二個及之後的參數是要發送的具體的消息
electron.ipcRenderer.send("render-to-main-message", message);

send方法至少需要兩個參數,第一個是事件名稱,在主線程中需要監聽此事件,然後是至少一個參數的事件參數,可以有多個,但是至少有一個。

在主線程main.js中接收事件:

// 接收從渲染進程發送到主進程的消息
ipcMain.on("render-to-main-message", (event, message) => {
 
    // 在控制檯上打印一下
    console.log(`receive message from render: ${message}`);
 
    // 回覆消息
    event.reply("main-to-render-message", `來自主進程:我收到了你的消息“${message}”`);
})

使用 event.reply 在主進程中回覆渲染進程發過來的消息,因爲這個replay指定了一個事件名稱,因此在渲染進程render.js中也要監聽事件才能收到回覆

// 接收主進程發來的消息
// 第一個參數是約定的事件的名稱
// 第二個參數是處理事件的callback
electron.ipcRenderer.on("main-to-render-message", (event, message) => {
    alert(message);
});

2.2 渲染進程向主進程發送同步消息

同步消息是渲染進程向主進程發送的,因爲渲染進程頁面可以有多個,而主進程node進程只有一個,因此渲染進程可以等主進程,而主進程不能同步等渲染進程。

渲染進程向主進程發送同步消息,使用 electron.ipcRenderer.sendSync 方法,這個方法的返回值是從主進程中返回的,在渲染進程render.js中向主進程發送消息:

const electron = require("electron");
// 發送同步消息
const replayMessage = electron.ipcRenderer.sendSync("render-to-main-message-sync", message);
alert(replayMessage);

在主進程main.js中接收並回復渲染進程發過來的同步消息:

// 接收同步消息
ipcMain.on("render-to-main-message-sync", (event, message) => {
 
    // 控制檯打印一下知道來了
    console.log(`receive sync message from render: ${message}`);
 
    // 回覆渲染進程的同步消息
    event.returnValue = `來自主進程:我收到了你的消息“${message}”`;
})

在主進程中對於同步消息和異步消息的接收沒有區別,只是回覆同步消息的時候變成了

event.returnValue = "要回復的消息內容"

2.3 主進程向渲染進程發送消息

渲染進程可以向主進程發送同步消息或者異步消息,但是主進程只能向渲染進程發送異步消息,比如下面是在主進程啓動後3秒向渲染進程發送一條消息:

function createWindow() {
    const window = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
            nodeIntegration: true
        }
    })
 
    // 注意這個路徑是從項目根路徑開始的
    window.loadFile("example/use-ipc/index.html")
 
    setTimeout(() => {
        window.webContents.send("main-to-render-message", "啓動完成了");
    }, 3000)
 
}

在渲染進程render.js中監聽此事件:

const electron = require("electron");
electron.ipcRenderer.on("main-to-render-message", (event, message) => {
    alert(message);
});

2.4 代碼及運行效果一覽

上面的三種發送方式都是隻提取了部分代碼做展示,完整的例子代碼如下:

main.js:

const {app, BrowserWindow, ipcMain} = require("electron")
 
function createWindow() {
    const window = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
            nodeIntegration: true
        }
    })
 
    // 注意這個路徑是從項目根路徑開始的
    window.loadFile("example/use-ipc/index.html")
 
    setTimeout(() => {
        window.webContents.send("main-to-render-message", "啓動完成了");
    }, 3000)
 
}
 
app.whenReady().then(createWindow)
 
app.on("window-all-closed", () => {
    if (process.platform !== "darwin") {
        app.quit()
    }
})
 
app.on("activate", () => {
    if (BrowserWindow.getAllWindows().length === 0) {
        createWindow()
    }
})
 
// 接收從渲染進程發送到主進程的消息
ipcMain.on("render-to-main-message", (event, message) => {
 
    // 在控制檯上打印一下
    console.log(`receive message from render: ${message}`);
 
    // 回覆消息
    event.reply("main-to-render-message", `來自主進程:我收到了你的消息“${message}”`);
})
 
// 接收同步消息
ipcMain.on("render-to-main-message-sync", (event, message) => {
 
    // 控制檯打印一下知道來了
    console.log(`receive sync message from render: ${message}`);
 
    // 回覆渲染進程的同步消息
    event.returnValue = `來自主進程:我收到了你的消息“${message}”`;
})

index.html文件(render.js沒有單獨提出來,render的js直接放到html中了):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>IPC通信</title>
</head>
<body>
<h1>IPC通信</h1>
<input type="text" id="message">
<button onclick="sendMessageToMainProcess()">發送消息給主進程</button>
 
<script type="text/javascript">
    const electron = require("electron");
 
    // 接收主進程發來的消息
    // 第一個參數是約定的事件的名稱
    // 第二個參數是處理事件的callback
    electron.ipcRenderer.on("main-to-render-message", (event, message) => {
        alert(message);
    });
 
    // 向主進程發送消息
    function sendMessageToMainProcess() {
        const message = document.getElementById("message").value;
 
        // 第一個參數是約定的事件的名稱,主進程要監聽這個事件
        // 第二個及之後的參數是要發送的具體的消息
        electron.ipcRenderer.send("render-to-main-message", message);
 
        // 發送同步消息
        const replayMessage = electron.ipcRenderer.sendSync("render-to-main-message-sync", message);
        alert(replayMessage);
    }
</script>
</body>
</html>
效果:

 

0

本文所用Electron版本:"electron": "^11.1.0"

 

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章