Electron -- 进程消息通知

本文介绍了使用electron开发时候和消息传递相关的知识,包括主进程和渲染进程之间的通信,以及Web页面和主进程之间的通信。

1. ipcMain.on监听的是什么消息

ipcMain.on用于在Electron主进程(ipcMain)中监听从渲染进程(ipcRenderer)发送的消息。它是一个事件监听器,可以注册特定的事件名称,并在收到对应事件时触发回调函数;例如:

js 复制代码
const { ipcMain } = require('electron');

// 监听来自渲染进程的消息
ipcMain.on('message', (event, arg) => {
  console.log(arg); // 打印接收到的消息
});

2. 如何在ipcRenderer(渲染进程)中向ipcMain发送消息

在渲染进程

js 复制代码
const { ipcRenderer } = require('electron');

// 发送消息给主进程
ipcRenderer.send('message', 'Hello from renderer process!');

// 监听来自主进程的回复消息
ipcRenderer.on('reply', (event, arg) => {
  console.log(arg); // 打印收到的回复消息
});

3. 如何在ipcMain中向ipcRenderer发送消息

3.1 在ipcMain中通过win.webContents对象向此win对象对应的ipcRender发送消息,例如

js 复制代码
const { ipcMain, BrowserWindow } = require('electron');

// 创建窗口对象
let win = new BrowserWindow();

// 监听来自渲染进程的消息
ipcMain.on('messageToMain', (event, arg) => {
  console.log(arg); // 打印接收到的消息

  // 向特定窗口的渲染进程发送消息
  win.webContents.send('messageFromMain', 'Hello from main process!');
});

3.2 ipcMain收到消息之后回复发送消息的ipcRenderer

利用消息传递过程中,回调函数第一个参数,即事件对象event上的reply对象属性进行消息传递(准确来说是消息传递),例如:

js 复制代码
// 监听来自渲染进程的消息
ipcMain.on('message', (event, arg) => {
  console.log(arg); // 打印接收到的消息
  // 发送回复消息给渲染进程
  event.reply('reply', 'Hello from main process!');
});

4. ipcRender上与消息通知相关的方法

下面是七个使用ipcRenderer进行消息通知的示例,包括ipcMain和ipcRenderer两侧的代码:

4.1. ipcRenderer.send(channel, ...args): 主进程(ipcMain)代码:

javascript 复制代码
const { ipcMain } = require('electron');

ipcMain.on('messageToMain', (event, arg) => {
  console.log(arg); // 打印接收到的消息
});

// 渲染进程发送消息到主进程
ipcRenderer.send('messageToMain', 'Hello from renderer process!');

渲染进程(ipcRenderer)代码:

javascript 复制代码
const { ipcRenderer } = require('electron');

// 向主进程发送异步消息
ipcRenderer.send('messageToMain', 'Hello from renderer process!');

4.2. ipcRenderer.sendSync(channel, ...args): 区别在于ipcRenderer.sendSync是有返回值的,而ipcRenderer.send没有;这个区别很好的体现出了同步通信和异步通信的区别。

主进程(ipcMain)代码:

javascript 复制代码
const { ipcMain } = require('electron');

ipcMain.on('messageToMainSync', (event, arg) => {
  console.log(arg); // 打印接收到的消息

  // 向渲染进程返回同步消息
  event.returnValue = 'Hello back from main process!';
});

// 渲染进程发送同步消息到主进程
const result = ipcRenderer.sendSync('messageToMainSync', 'Hello from renderer process!');
console.log(result); // 打印接收到的返回结果

渲染进程(ipcRenderer)代码:

javascript 复制代码
const { ipcRenderer } = require('electron');

// 向主进程发送同步消息
const result = ipcRenderer.sendSync('messageToMainSync', 'Hello from renderer process!');
console.log(result); // 打印接收到的返回结果

4.3. ipcRenderer.invoke(channel, ...args)

  • 需要注意的是ipcRenderer.invoke和icpMain.handle搭配使用,和上面的ipcRenderer.send搭配ipcMain.on是不同的。
  • icpMain.handle的返回值是一个Promise对象,此对象包裹的数据正是ipcRenderer.invoke.then的接受数据。

主进程(ipcMain)代码:

javascript 复制代码
const { ipcMain } = require('electron');

ipcMain.handle('messageInvoke', async (event, arg) => {
  console.log(arg); // 打印接收到的消息

  // 模拟处理过程,返回Promise结果
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('Hello back from main process!');
    }, 1000);
  });
});

// 渲染进程发送异步消息到主进程,并等待返回结果
ipcRenderer.invoke('messageInvoke', 'Hello from renderer process!')
  .then((result) => {
    console.log(result); // 打印接收到的返回结果
  });

渲染进程(ipcRenderer)代码:

javascript 复制代码
const { ipcRenderer } = require('electron');

// 向主进程发送异步消息,并等待返回结果
ipcRenderer.invoke('messageInvoke', 'Hello from renderer process!')
  .then((result) => {
    console.log(result); // 打印接收到的返回结果
  });

4.4. ipcRenderer.on(channel, listener): 正如前文所说:ipcRenderer.on和ipcRenderer.send或者win.webContents.send搭配使用。 主进程(ipcMain)代码:

javascript 复制代码
const { ipcMain } = require('electron');

ipcMain.on('messageToMain', (event, arg) => {
  console.log(arg); // 打印接收到的消息

  // 向渲染进程发送回复消息
  event.reply('messageFromMain', 'Hello back from main process!');
});

渲染进程(ipcRenderer)代码:

javascript 复制代码
const { ipcRenderer } = require('electron');

// 监听来自主进程的消息
ipcRenderer.on('messageFromMain', (event, arg) => {
  console.log(arg); // 打印接收到的消息
});

// 向主进程发送消息
ipcRenderer.send('messageToMain', 'Hello from renderer process!');

4.5. ipcRenderer.once(channel, listener): 主进程和渲染进程示例与示例4。4中的代码相同。唯一不同之处是使用ipcRenderer.once替代ipcRenderer.on,以确保监听器仅触发一次。

4.6. ipcRenderer.removeListener(channel, listener): 主进程和渲染进程示例与示例4中的代码相同。在需要移除特定监听器时,使用ipcRenderer.removeListener方法。

4.7. ipcRenderer.removeAllListeners([channel]): 移除所有或指定channel的监听器。

5. Web页面和主进程之间的通信

Web页面和主进程之间的通信的本质是ipcRenderer和ipcMain之间进行通信,本质上就是4中的7种方法;不同之处在于:

  • 在Electron中,为了确保Web页面与主进程之间的通信安全,需要使用contextBridge模块来限制对Electron API的访问。contextBridge提供了exposeInMainWorld方法,用于在渲染进程中暴露特定的API给主进程,以便进行双向通信。
  • 通过exposeInMainWorld,可以将自定义的API对象或函数注入到渲染进程的全局作用域中,使其可以直接在页面中访问,并与主进程进行通信。
javascript 复制代码
const { contextBridge, ipcRenderer } = require('electron');

// 
contextBridge.exposeInMainWorld('electronAPI', {

    // web页面获取渲染进程中的相关信息
    isPrimaryScreen: () => true,

    // web页面操作主进程方法
    exitApp: () => void ipcRenderer.send('closeMainWindow'),

    // web页面向主进程传递数据
    updateFocusWindow: index => void ipcRenderer.send('update-focus-window', index),

    // web页面将消息的回调函数注册到ipcRender中
    handleClearLocalStorage: callback => void ipcRenderer.on('clear-localStorage', callback),

    // web页面向主进程获取进程数据
    getLocalIP: () => ipcRenderer.invoke('get-local-ip'),

});

使用:

js 复制代码
console.log(window?.electronAPI.getLocalIP().then(data => data));
相关推荐
艾小逗1 小时前
vue3中的effectScope有什么作用,如何使用?如何自动清理
前端·javascript·vue.js
小小小小宇4 小时前
手写 zustand
前端
Hamm4 小时前
用装饰器和ElementPlus,我们在NPM发布了这个好用的表格组件包
前端·vue.js·typescript
明似水5 小时前
Flutter 弹窗队列管理:支持优先级的线程安全通用弹窗队列系统
javascript·安全·flutter
小小小小宇5 小时前
前端国际化看这一篇就够了
前端
大G哥5 小时前
PHP标签+注释+html混写+变量
android·开发语言·前端·html·php
whoarethenext5 小时前
html初识
前端·html
小小小小宇5 小时前
一个功能相对完善的前端 Emoji
前端
m0_627827525 小时前
vue中 vue.config.js反向代理
前端
Java&Develop5 小时前
onloyoffice历史版本功能实现,版本恢复功能,编辑器功能实现 springboot+vue2
前端·spring boot·编辑器