Electron 主进程给渲染进程发消息,渲染进程收不到的问题
正常接收的
先看个正常的代码
主进程
//为了管理应用程序的生命周期事件以及创建和控制浏览器窗口,您从 electron 包导入了 app 和 BrowserWindow 模块 。
const { app, BrowserWindow,ipcMain } = require('electron')
//在此之后,你定义了一个创建 新的浏览窗口的函数并将 nodeIntegration 设置为 true,将 index.html 文件加载到窗口中(第 12 行,稍后我们将讨论该文件)
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
//是否注入nodeapi
nodeIntegration: true,
//渲染进程是否启用remote模块
enableRemoteModule: true
}
})
win.loadFile('index.html')
//2s后 , 主动发送
setTimeout(()=>{
win.webContents.send('send-message-to-render-test', '这是主进程的主动搭讪')
}, 2000)
}
//你通过调用 createWindow方法,在 electron app 第一次被初始化时创建了一个新的窗口。
app.whenReady().then(createWindow)
//您添加了一个新的侦听器,当应用程序不再有任何打开窗口时试图退出。 由于操作系统的 窗口管理行为 ,此监听器在 macOS 上是禁止操作的
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
//您添加一个新的侦听器,只有当应用程序激活后没有可见窗口时,才能创建新的浏览器窗口。 例如,在首次启动应用程序后或重启运行中的应用程序
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
渲染进程
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>进程通信</title>
</head>
<body>
<h1>进程通信</h1>
<button onclick="sendMessageMain()">发送信息给主进程</button>
</body>
<script>
const { ipcRenderer } = require('electron');
//监听
ipcRenderer.on('send-message-to-render-test', (event, arg) => {
console.log('渲染进程收到的消息:',arg)
})
</script>
</html>
可以看到能够正常的接收
去掉延时发送
这时候你去掉延时发送,你会发现收不到了
更改后的主进程
//为了管理应用程序的生命周期事件以及创建和控制浏览器窗口,您从 electron 包导入了 app 和 BrowserWindow 模块 。
const { app, BrowserWindow,ipcMain } = require('electron')
//在此之后,你定义了一个创建 新的浏览窗口的函数并将 nodeIntegration 设置为 true,将 index.html 文件加载到窗口中(第 12 行,稍后我们将讨论该文件)
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
//是否注入nodeapi
nodeIntegration: true,
//渲染进程是否启用remote模块
enableRemoteModule: true
}
})
win.loadFile('index.html')
win.webContents.send('send-message-to-render-test', '这是主进程的主动搭讪')
}
//你通过调用 createWindow方法,在 electron app 第一次被初始化时创建了一个新的窗口。
app.whenReady().then(createWindow)
//您添加了一个新的侦听器,当应用程序不再有任何打开窗口时试图退出。 由于操作系统的 窗口管理行为 ,此监听器在 macOS 上是禁止操作的
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
//您添加一个新的侦听器,只有当应用程序激活后没有可见窗口时,才能创建新的浏览器窗口。 例如,在首次启动应用程序后或重启运行中的应用程序
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
啥也没有
这是为啥呢?
原因分析
我们看下官网写法
https://www.electronjs.org/docs/api/web-contents#contentssendchannel-args
// 在主进程中. const { app, BrowserWindow } = require('electron') let win = null app.whenReady().then(() => { win = new BrowserWindow({ width: 800, height: 600 }) win.loadURL(`file://${__dirname}/index.html`) win.webContents.on('did-finish-load', () => { win.webContents.send('ping', 'whoooooooh!') }) })
从上面看是监听一个did-finish-load
事件,那这个事件是干嘛的呢,官网也有说明
导航完成时触发,即选项卡的旋转器将停止旋转,并指派
onload
事件后。返回:
event
EventerrorCode
IntegererrorDescription
StringvalidatedURL
StringisMainFrame
BooleanframeProcessId
IntegerframeRoutingId
Integer
简单理解就是渲染进程的页面加载完了之后再触发,到这里就明白了 ,主进程主动给渲染进程发送消息必须在渲染进程页面渲染完成之后才可以。
解决办法
主进程加上监听 如
win.webContents.on('did-finish-load', () => {
win.webContents.send('ping', 'whoooooooh!')
})
将最开始的延时改成监听
//为了管理应用程序的生命周期事件以及创建和控制浏览器窗口,您从 electron 包导入了 app 和 BrowserWindow 模块 。
const { app, BrowserWindow,ipcMain } = require('electron')
//在此之后,你定义了一个创建 新的浏览窗口的函数并将 nodeIntegration 设置为 true,将 index.html 文件加载到窗口中(第 12 行,稍后我们将讨论该文件)
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
//是否注入nodeapi
nodeIntegration: true,
//渲染进程是否启用remote模块
enableRemoteModule: true
}
})
win.loadFile('index.html')
win.webContents.on('did-finish-load',() => {
win.webContents.send('send-message-to-render-test', '这是主进程的主动搭讪')
})
}
//你通过调用 createWindow方法,在 electron app 第一次被初始化时创建了一个新的窗口。
app.whenReady().then(createWindow)
//您添加了一个新的侦听器,当应用程序不再有任何打开窗口时试图退出。 由于操作系统的 窗口管理行为 ,此监听器在 macOS 上是禁止操作的
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
//您添加一个新的侦听器,只有当应用程序激活后没有可见窗口时,才能创建新的浏览器窗口。 例如,在首次启动应用程序后或重启运行中的应用程序
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
效果