zoukankan      html  css  js  c++  java
  • Electron笔记之进程间通信(ipc)


    一、主进程和渲染进程

    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({
             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({
             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"

  • 相关阅读:
    RPC简介
    RabbitMQ从入门到精通
    flask 源码解析:响应
    flask 源码解析:请求
    flask 源码解析:上下文
    flask 源码解析:应用启动流程
    flask 源码解析:路由
    flask源码分析—简介
    11-Docker网络扩展
    10-Docker之Docker-Compose
  • 原文地址:https://www.cnblogs.com/cc11001100/p/14290450.html
Copyright © 2011-2022 走看看