zoukankan      html  css  js  c++  java
  • Electron 主进程给渲染进程发消息,渲染进程收不到的问题

    正常接收的

    先看个正常的代码

    主进程

    //为了管理应用程序的生命周期事件以及创建和控制浏览器窗口,您从 electron 包导入了 app 和 BrowserWindow 模块 。
    const { app, BrowserWindow,ipcMain } = require('electron')
    
    //在此之后,你定义了一个创建 新的浏览窗口的函数并将 nodeIntegration 设置为 true,将 index.html 文件加载到窗口中(第 12 行,稍后我们将讨论该文件)
    function createWindow () {
        const win = new BrowserWindow({
             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>
    

    image-20210303093912975

    可以看到能够正常的接收

    去掉延时发送

    这时候你去掉延时发送,你会发现收不到了

    更改后的主进程

    //为了管理应用程序的生命周期事件以及创建和控制浏览器窗口,您从 electron 包导入了 app 和 BrowserWindow 模块 。
    const { app, BrowserWindow,ipcMain } = require('electron')
    
    //在此之后,你定义了一个创建 新的浏览窗口的函数并将 nodeIntegration 设置为 true,将 index.html 文件加载到窗口中(第 12 行,稍后我们将讨论该文件)
    function createWindow () {
        const win = new BrowserWindow({
             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()
        }
    })
    

    啥也没有

    image-20210303094152507

    这是为啥呢?

    原因分析

    我们看下官网写法

    https://www.electronjs.org/docs/api/web-contents#contentssendchannel-args

    // 在主进程中.
    const { app, BrowserWindow } = require('electron')
    let win = null
    
    app.whenReady().then(() => {
    win = new BrowserWindow({  800, height: 600 })
    win.loadURL(`file://${__dirname}/index.html`)
    win.webContents.on('did-finish-load', () => {
     win.webContents.send('ping', 'whoooooooh!')
    })
    })
    

    从上面看是监听一个did-finish-load事件,那这个事件是干嘛的呢,官网也有说明

    实例事件

    Event: 'did-finish-load'

    导航完成时触发,即选项卡的旋转器将停止旋转,并指派onload事件后。

    Event: 'did-fail-load'

    返回:

    • event Event
    • errorCode Integer
    • errorDescription String
    • validatedURL String
    • isMainFrame Boolean
    • frameProcessId Integer
    • frameRoutingId 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({
             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()
        }
    })
    

    效果

    image-20210303102502995

  • 相关阅读:
    Dockerfile使用案例
    Centos创建sudo用户免密使用
    yaml实例
    k8s学习过程中需要注意的地方
    docker部署redmine项目管理软件
    kubernetes陈述式常用命令
    mysql误删除数据后如何恢复
    kubeadm安装的k8s集群卸载方式
    虚拟机vmware centos7 扩展磁盘空间
    'React/RCTBundleURLProvider.h' file not found
  • 原文地址:https://www.cnblogs.com/makalochen/p/14472976.html
Copyright © 2011-2022 走看看