当前位置:网站首页>Introduction to electron tutorial 3 - process communication
Introduction to electron tutorial 3 - process communication
2022-04-23 19:46:00 【Harm the evil king】
Welcome to Electron The third tutorial of the introductory tutorial , This section is very important ! Interprocess communication (IPC) Is in Electron A key part of building feature rich desktop applications in . Because the main process and rendering process are Electron There are different responsibilities in the process model ,IPC Is the only way to perform many common tasks , For instance from UI Call local API Or trigger from local menu web Changes in content . Let's introduce in detail 3 A common way of communication .
* One way communication between rendering process and main process
stay Electron in , The process is defined by the developer “ passageway ” And ipcMain
Module and ipcRenderer
Module to communicate . These channels are Any of the ( You can name them as you like ) and Bidirectional ( You can use the same channel name for both modules ). To send a one-way message from the rendering process to the main process IPC news , You can pre render the script again preload.js Use in ipcRenderer
send out API Send a message , And then in main.js In the use ipcMain.on
receive . You usually use this pattern from your web Call a middle note in the content API. We will demonstrate this pattern by creating a simple application , The application can programmatically change the title of the window .
Let's use code to demonstrate this process , Here are all the codes of the case :
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Process of communication </title>
</head>
<body>
Title: <input id="title"/>
<button id="btn" type="button">Set</button>
<script src="./index.js"></script>
</body>
</html>
preload.js
const {
contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {
setTitle: (title) => ipcRenderer.send('set-title', title)
})
index.js
const setButton = document.getElementById('btn')
const titleInput = document.getElementById('title')
setButton.addEventListener('click', () => {
const title = titleInput.value
window.electronAPI.setTitle(title)
});
main.js
const {
app, BrowserWindow, ipcMain} = require('electron')
const path = require('path')
function createWindow () {
const mainWindow = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
ipcMain.on('set-title', (event, title) => {
const webContents = event.sender
const win = BrowserWindow.fromWebContents(webContents)
win.setTitle(title)
})
mainWindow.loadFile('index.html')
}
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
The operation effect is as follows (GIF It's a little slow , Don't you mind? ):
Here are some key points of the code :
1. Listen for events in the main process
In the main process , We use ipcMain
stay set-title
Set a... On the channel IPC Monitor , This set-title
We are pre rendering the script preload.js The interface channel defined inside .
ipcMain.on('set-title', (event, title) => {
const webContents = event.sender
const win = BrowserWindow.fromWebContents(webContents)
win.setTitle(title)
})
Whenever a message passes set-title
Channel incoming , This function will find the attached to the message sender BrowserWindow
example , And use win.setTitle
Set the title of the application window .
2. Define the interface channel in the preload script
To send a message to the listener created above , You can use ipcRenderer
. send out API. By default , The renderer process did not Node.js or Electron Module access . As an application developer , You need to use contextBridge
Select which from the preloaded scripts to expose API. here , You will be able to use window.electronAPI.setTitle()
function .
const {
contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {
setTitle: (title) => ipcRenderer.send('set-title', title)
})
* Two way communication between rendering process and main process
two-way IPC A common application is to invoke the middle note module from the rendering process code and wait for the result. . This can be done by using ipcRenderer.invoke
To achieve , call ipcMain.handle
pairing . In the following example , We will open a select local file dialog from the rendering process , And return the path of the selected file .
Here are all the codes involved in the case :
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Process of communication </title>
</head>
<body>
<button type="button" id="btn">Open a File</button>
File path: <strong id="filePath"></strong>
<script src='./index.js'></script>
</body>
</html>
index.js
const btn = document.getElementById('btn')
const filePathElement = document.getElementById('filePath')
btn.addEventListener('click', async () => {
const filePath = await window.electronAPI.openFile()
filePathElement.innerText = filePath
})
main.js
const {
app, BrowserWindow, ipcMain,dialog} = require('electron')
const path = require('path')
async function handleFileOpen() {
const {
canceled, filePaths } = await dialog.showOpenDialog()
if (canceled) {
return ""
} else {
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('openFileDialog', 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')
contextBridge.exposeInMainWorld('electronAPI',{
openFile: () => ipcRenderer.invoke('openFileDialog')
})
Running effect demonstration :
Here are some key points of the code :
1. Define the event handler function in the main process , And monitor ICP Interface call
In the main process , We will create a call dialog
Modular showOpenDialog
Function of method handleFileOpen()
, The value used to return the file path selected by the user . After the application is ready , It calls ipcMain.handle()
To monitor the rendering process ipcRenderer.invoke('openFileDialog')
The definition of openFileDialog
. When index.js It calls window.electronAPI.openFile()
when , Will trigger openFileDialog
, After being monitored and processed by the main process , Return results .
2. Call to define the interface through the preloaded script
In the preload script , We opened a single line openFile
function , It calls and returns ipcRederer .invoke('openFileDialog')
.
stay index.js In the code snippet , We're listening to #btn
Button click , And call window.electronAPI.openFile()
To activate local openFile
Dialog box . And then in #filePath
Element displays the selected file path .
3. ipcRenderer.invoke An alternative
ipcRenderer.invoke()
There are two alternatives :
(1)ipcRenderer.send()
: The one-way communication we use can also be used to perform two-way communication . This is Electron 7 Passed before IPC Recommended method for asynchronous two-way communication .
preload.js
const {
ipcRenderer } = require('electron')
ipcRenderer.on('asynchronous-reply', (_event, arg) => {
console.log(arg)
// prints pong
})
ipcRenderer.send('asynchronous-message', 'ping')
main,js
ipcMain.on('asynchronous-message', (event, arg) => {
console.log(arg)
// I will promise ping
event.reply('asynchronous-reply', 'pong')
})
(1) ipcRenderer.sendSync()
: This method sends a message to the main process , And wait for the response synchronously .
preload.js
const {
ipcRenderer } = require('electron')
const result = ipcRenderer.sendSync('synchronous-message', 'ping')
console.log(result)
// prints pong
main.js
const {
ipcMain } = require('electron')
ipcMain.on('synchronous-message', (event, arg) => {
console.log(arg)
// prints ping
event.returnValue = 'pong'
})
The structure of this code is very similar to the call model , But for performance reasons , We recommend avoiding this API. Its synchronous nature means that it will block the renderer process , Until a reply is received .
* One way communication from the main process to the rendering process
When a message is sent from the main process to the rendering process , You need to specify which renderer is receiving the message . The message needs to pass through the main process WebContents
The instance is sent to the rendering process . This WebContents
The instance contains a sent
Method , Can be like ipcReender .send
Use it like that . To demonstrate this communication mode , A digital counter controlled by the menu bar will be built .
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Process of communication </title>
</head>
<body>
Current value: <strong id="counter">0</strong>
<script src='./index.js'></script>
</body>
</html>
preload.js
const {
contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {
handleCounter: (callback) => ipcRenderer.on('update-counter', callback)
})
index.js
const counter = document.getElementById('counter')
window.electronAPI.handleCounter((event, value) => {
const oldValue = Number(counter.innerText)
const newValue = oldValue + value
counter.innerText = newValue
event.sender.send('counter-value', newValue)
})
main.js
const {
app, BrowserWindow, Menu, ipcMain} = require('electron')
const path = require('path')
function createWindow () {
const mainWindow = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
const menu = Menu.buildFromTemplate([
{
label: app.name,
submenu: [
{
click: () => mainWindow.webContents.send('update-counter', 1),
label: 'Increment',
},
{
click: () => mainWindow.webContents.send('update-counter', -1),
label: 'Decrement',
}
]
}
])
Menu.setApplicationMenu(menu)
mainWindow.loadFile('index.html')
// Open the DevTools.
mainWindow.webContents.openDevTools()
}
app.whenReady().then(() => {
ipcMain.on('counter-value', (_event, value) => {
console.log(value) // will print value to Node console
})
createWindow()
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
Running effect demonstration :
Explain part of the code :
We first need to use it in the main process Electron Of Menu
The module builds a custom menu , Send... From the main process to the target renderer IPC news . Click the handler to send a message to the renderer process through the counter channel (1 or -1).
const menu = Menu.buildFromTemplate([
{
label: app.name,
submenu: [
{
click: () => mainWindow.webContents.send('update-counter', 1),
label: 'Increment',
},
{
click: () => mainWindow.webContents.send('update-counter', -1),
label: 'Decrement',
}
]
}
])
Menu.setApplicationMenu(menu)
Just like the main process to the previous example , We are preloading the script preload.js Use in contextBridge
and ipcRederer
The module exposes to the rendering process IPC function :
const {
contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {
handleCounter: (callback) => ipcRenderer.on('update-counter', callback)
})
* Communication between rendering processes
stay Electron in , There is no direct method to use between rendering processes ipcMain
and ipRenderer
Module sends messages , And this communication method is actually very rarely used . Do that , You can use the main process as a message broker between renderers . This will involve sending messages from a renderer to the main process , The main process forwards the message to another renderer , I'm not going to do the demo here .
版权声明
本文为[Harm the evil king]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204231940533385.html
边栏推荐
- Electron入门教程3 ——进程通信
- kibana 报错 server is not ready yet 可能的原因
- Video understanding
- JVM的类加载过程
- Project training of Software College of Shandong University - Innovation Training - network security shooting range experimental platform (V)
- Why is the hexadecimal printf output of C language sometimes with 0xff and sometimes not
- SRS 的部署
- 对普通bean进行Autowired字段注入
- Easy mock local deployment (you need to experience three times in a crowded time. Li Zao will do the same as me. Love is like a festival mock)
- antd dropdown + modal + textarea导致的textarea光标不可被键盘控制问题
猜你喜欢
Project training of Software College of Shandong University - Innovation Training - network security shooting range experimental platform (6)
C6748 软件仿真和硬件测试 ---附详细FFT硬件测量时间
Understanding various team patterns in scrum patterns
OpenHarmony开源开发者成长计划,寻找改变世界的开源新生力!
Virtual machine performance monitoring and fault handling tools
【webrtc】Add x264 encoder for CEF/Chromium
Build intelligent garbage classification applet based on Zero
MFCC: Mel频率倒谱系数计算感知频率和实际频率转换
Physical meaning of FFT: 1024 point FFT is 1024 real numbers. The actual input to FFT is 1024 complex numbers (imaginary part is 0), and the output is also 1024 complex numbers. The effective data is
C6748 software simulation and hardware test - with detailed FFT hardware measurement time
随机推荐
Thoughts on the optimization of examination papers in the examination system
深度分析数据恢复原理——那些数据可以恢复那些不可以数据恢复软件
OpenHarmony开源开发者成长计划,寻找改变世界的开源新生力!
Possible root causes include a too low setting for -Xss and illegal cyclic inheritance dependencies
Physical meaning of FFT: 1024 point FFT is 1024 real numbers. The actual input to FFT is 1024 complex numbers (imaginary part is 0), and the output is also 1024 complex numbers. The effective data is
Kubernetes入门到精通-裸机LoadBalence 80 443 端口暴露注意事项
VeraCrypt文件硬盘加密使用教程
Electron入门教程4 —— 切换应用的主题
MySQL practical skills
Decompile and get the source code of any wechat applet - just read this (latest)
An example of using JNI to directly access surface data
@MapperScan与@Mapper
RuntimeError: Providing a bool or integral fill value without setting the optional `dtype` or `out`
Speex维纳滤波与超几何分布的改写
图书管理数据库系统设计
Pit encountered using camera x_ When onpause, the camera is not released, resulting in a black screen when it comes back
一个简单的(基于redisson的)分布式同步工具类封装
山东大学软件学院项目实训-创新实训-网络安全靶场实验平台(八)
【2022】将3D目标检测看作序列预测-Point2Seq: Detecting 3D Objects as Sequences
Go modules daily use