6.进程间通信 IPC
-- 未经授权禁止转载 --

进程间通信 IPC(Inter-Process Communication)

Electron 应用由多个进程组成, 包括一个主进程和一个或多个渲染进程

进程之间由于安全原因不能直接共享数据, 需通过 IPC 来进行数据交换


新版 Electron 推荐使用双向通信 ipcRenderer.invoke 和 ipcMain.handle 进行进程间的通信

不推荐使用传统的单向通信 ipcRenderer.send 和 ipcMain.on


ipcRenderer.invoke 发送请求并等待响应, 返回一个 Promise

ipcRenderer.send 发送请求但不等待响应, 没有返回值


ipcMain.handle 在主进程中定义, 是接收者, 用于接收来自渲染进程的消息

ipcRenderer.invoke 在预加载脚本中调用, 是发送者, 用于向主进程发送消息


ipcRenderer.invoke(channel, data)

     channel 是一个字符串,用于标识通信的通道,不同的通道名称可以调用不同的功能

     发送者通过指定的 channel 发送数据,接收者通过监听相同的 channel 来接收数据


main.js
      import { app, BrowserWindow, ipcMain } from "electron"
      import url from 'url'
      import path from 'path'
      import os from 'os'

      let __filename = url.fileURLToPath(import.meta.url)
      let __dirname = path.dirname(__filename)

      //console.log(os.version()) //内核版本
      //console.log("邓瑞编程")

      //创建窗口
      const createWindow = () => {
          const mainWindow = new BrowserWindow({
              width: 1300, //设置窗口宽度(单位:像素)
              height: 750, //设置窗口高度
              icon: "resource/images/code.ico", //设置窗口图标
              autoHideMenuBar:true, //隐藏菜单栏
              //resizable: false, //禁止调整窗口大小
              //x:0, //x表示窗口左上角的水平坐标(单位:像素)
              //y:0, //y表示窗口左上角的垂直坐标
              webPreferences: { //网页偏好设置
                  nodeIntegration: true, //允许在渲染进程中直接使用 Node.js API
                  contextIsolation: true, //启用上下文隔 (提高安全性)
                  preload: path.resolve(__dirname,"resource/preload/preload.mjs"), //预加载脚本
              }
          })

          //mainWindow.loadURL("https://www.dengruicode.com") //加载指定的 url
          mainWindow.loadFile("resource/renderer/views/index.html") //加载本地 html

          //当尝试打开新窗口时, 阻止默认行为, 在当前窗口加载 url
          mainWindow.webContents.setWindowOpenHandler(details =>{
              mainWindow.loadURL(details.url)
              return { action: 'deny' } //阻止默认行为
          })
      }

      //当应用准备就绪后创建窗口
      app.whenReady().then(() => {
          createWindow()
      })

      //定义了一个处理函数, 用于响应名为 sendDataToMain 的异步调用
      //当渲染进程通过 sendDataToMain 发起调用时, 处理函数会被触发
      ipcMain.handle("sendDataToMain", (e,data) => {
          console.log(data)

          return data
      })


preload.mjs
      import os from 'os'
      import { contextBridge, ipcRenderer } from "electron"

      //console.log("preload.mjs")

      contextBridge.exposeInMainWorld('DRAPI',{
          url:"dengruicode.com",
          version:os.version(),
          sendDataToMain: async data => {
              //向主进程发起一个名为 sendDataToMain 的异步调用, 并携带 data 数据
              return await ipcRenderer.invoke('sendDataToMain',data)
          }    
      })

index.js
      //console.log("index.js", "dengruicode.com")
      //console.log("index.js", window)

      //渲染进程向主进程发送数据并获取返回值
      DRAPI.sendDataToMain("dengruicode.com").then(data => {
          console.log("data:", data)
      }).catch(err => {
          console.log("err:", err)
      })