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)

posted @ 2024-11-04 18:14  Felix_Openmind  阅读(5)  评论(0编辑  收藏  举报