Electron: 渲染器进程到主进程(双向)
双向IPC的一个常见应用:从渲染器进程代码调用主进程模块并等待结果
【ipcRenderer.invoke】《==============》【ipcMain.handle()】
main.js
const { app, BrowserWindow, ipcMain, dialog } = require('electron/main')
const path = require('node:path')
async function handleFileOpen () {
const { canceled, filePaths } = await dialog.showOpenDialog()
if (!canceled) {
return filePaths[0]
}
}
function createWindow () {
const mainWindow = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
mainWindow.loadFile('index.html')
}
app.whenReady().then(() => {
// 🥑 ipcMain.handle监听事件
// 创建handleFileOpen()函数,调用dialog.showOpenDialog并返回用户选择的文件路径之
// 当渲染器进程通过dialog:openFile通道发送ipcRender.invoke消息时,此函数被用作一个回调
// 返回值将作为一个Promise返回到最初的invoke调用
// 🔺IPC 通道名称上的 dialog: 前缀对代码没有影响。 它仅用作命名空间以帮助提高代码的可读性。
ipcMain.handle('dialog:openFile', handleFileOpen)
createWindow()
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
preload.js
const { contextBridge, ipcRenderer } = require('electron/renderer')
// 🥑 通过预加载脚本暴露ipcRenderer.invoke
// 预加载脚本中暴露一个单行的openFile函数,调用并返回ipcRenderer.invoke('dialog:openFile')的值
contextBridge.exposeInMainWorld('electronAPI', {
// 🔺 不会直接暴露整个ipcRenderer.invoke
openFile: () => ipcRenderer.invoke('dialog:openFile')
})
renderer.js
const btn = document.getElementById('btn')
const filePathElement = document.getElementById('filePath')
btn.addEventListener('click', async () => {
// window.electronAPI.openFile() API来激活原生的打开文件对话框
const filePath = await window.electronAPI.openFile()
filePathElement.innerText = filePath
})
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
<title>Dialog</title>
</head>
<body>
// 构建渲染器进程UI
<button type="button" id="btn">Open a File</button>
File path: <strong id="filePath"></strong>
<script src='./renderer.js'></script>
</body>
</html>
使用ipcRenderer.sendSync API向主进程发送消息并同步等待响应
* main.js(Main Process)
ipcMain.on('synchronous-message', (event, arg) => {
console.log(arg) // 在Node控制台中打印"ping"
event.returnValue = 'pong'
})
* preload.js(Preload Script)
const { ipcRenderer } = require('electron')
const result = ipcRenderer.sendSync('synchronous-message', 'ping')
console.log(result)
学而不思则罔,思而不学则殆!