进程间通信

创建时间:2025-05-08 18:19
长度:4409
浏览:0
评论:0

为了将Electron的不同类型的进程桥接在一起,我们需要使用被称为预加载preload的脚本


可用的API详细信息
Electron模块渲染进程模块
Node.js模块events、timers、url
Pollfilled的全局模块Buffer、process、clearImmediate、setImmediate


preload脚本Demo

  创建一个preload.js

   然后在需要的进程里加载

   注意:可以用的api在上面有说明, 在文档可以看一下这些模块有什么属性/方法:  https://www.electronjs.org/zh/docs/latest/api/process#processversionschrome-%E5%8F%AA%E8%AF%BB

   preload.js

const { contextBridge } = require('electron');

const versions = contextBridge.exposeInMainWorld('versions', {
    node: process.versions.node,
    chrome: process.versions.chrome,
    electron: process.versions.electron
});

module.exports = versions;


   在main文件中加载

const { app, BrowserWindow } = require('electron');
const path  = require('path');

function createWindow () {
    let win = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
            preload: path.join(__dirname, 'preload.js')
        }
    })
    win.loadFile('index.html');
    win.webContents.openDevTools();
    return win;
}    


注意: 在index.html页面,我们就可以使用window.versions来访问或执行对应的方法了


IPC通信

   Electron 的 IPC(Inter-Process Communication,进程间通信)机制允许主进程和渲染进程之间的双向通信,是构建功能丰富的桌面应用的关键


    • 主进程使用 ipcMain:监听和处理来自渲染进程的消息。]
    • 渲染进程使用 ipcRenderer:向主进程发送消息或接收回复。


   单向进程

       主要两个方法

       ipcRenderer.send(发送) 和ipcMain.on(接收)

   

   demo: 修改窗口标题(单向进程)

   index.html 的script

const demo2 = function() {
    let btn = document.querySelector('.demo2 button');
    let input = document.querySelector('.demo2 input');

    btn.addEventListener('click', () => {
        let title = input.value;
        window.electron.setTitle(title)
    })
}


preload.js

const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electron', {
    setTitle(title) {
        return ipcRenderer.send('set-title', title)
    }
})


main.js

const { app, BrowserWindow, ipcMain } = require('electron');

// ...
// app是BrowserWindow的一个实例

app.on('ready', () => {
    let parent = createWindow();
    // createChildWindow(parent);

    ipcMain.on('set-title', (event, title) => {
        console.log('title, ', title)
        const webContents = event.sender;
        // 获取渲染进程(当前渲染的窗口)实列
        const win = BrowserWindow.fromWebContents(webContents);
        // 修改窗口
        win.setTitle(title);
    })
})

       ipcMain的event说明:  https://www.electronjs.org/zh/docs/latest/api/structures/ipc-main-event


   双向通信

       双向通信 - 从渲染器进程到主进程,再从主进程到渲染进程

       主要的两个方法: ipcRenderer.invoke(发送) 和ipcMain.handle(响应)

       写法都差不多,调用的api不同,多了一个返回值而已


   写入文件内容并响应(demo)

          index.html

btn.addEventListener('click', async() => {
    let content = input.value || 'string';
    const size = await window.electron.handleWriteFile(content);
    console.log('响应值', size )
})


preload.js


handleWriteFile(content) {
    console.log('ipcrenderer')
    console.log(content, 'content')
    return ipcRenderer.invoke('write-file', content);
}


main.js

const { app, BrowserWindow, ipcMain } = require('electron');
const path  = require('path');
const fs = require('fs');

function createWindow () {
    let win = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
            preload: path.join(__dirname, 'preload.js')
        }
    })
    win.loadFile('index.html');
    win.webContents.openDevTools();
    return win;
}

app.on('ready', () => {
    ipcMain.handle('write-file', async(event, content) => {
        await fs.promises.writeFile('test.txt', content);
        const textFile = await fs.promises.stat('test.txt');
        // 主要是这里要响应,渲染进程就可以接收到了。
        return textFile.size;
    });

    createWindow();
})


   主进程向渲染进程通信

       通过win.webContents.send();

   

main.js

const { app, BrowserWindow, ipcMain } = require('electron');
function createWindow () {
    let win = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
            preload: path.join(__dirname, 'preload.js')
        }
    })
    win.loadFile('index.html');
    win.webContents.openDevTools();
    return win;
}

app.on('ready', () => {
    const win = createWindow();
    let count = 0;
    win.webContents.send('update-count', count);
    setInterval(() => {
        count++;
        win.webContents.send('update-count', count);
    }, 1000);
})

   

preload.js

const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electron', {
    updateCounter(callback) {
        return ipcRenderer.on('update-count', callback)
    }
})


index.html

window.electron.updateCounter((event, count) => {
    console.log(count, 'count')
})







评论(共0条)