简体   繁体   中英

Why does it look like IPC messages from one menu item in Electron reach my window, but not when sent from another menu iteam?

I have a simple application that needs to run a background process to get some data. I would like to show a loading indicator while the data is being retrieved and I am having trouble with getting that done.

I am using ipcrenderer to receive the message in the main window. My code is below:

//// main.js

const electron = require('electron');
const url = require('url');
const path = require('path');

const {
  app,
  BrowserWindow,
  Menu,
  ipcMain
} = electron

// SET ENV
//process.env.NODE_ENV = 'production';

let mainWindow;
let addWindow;
let workerWindow;

// Listen for app to be ready
app.on('ready', function () {
  // Create new window
  mainWindow = new BrowserWindow({});
  // Load the HTML file into the window
  mainWindow.loadURL(url.format({
    pathname: path.join(__dirname, 'mainWindow.html'),
    protocol: 'file',
    slashes: true
  }));

  // Quit app when closed
  mainWindow.on('closed', function () {
    app.quit();
  })

  // Build menu from menu template
  const mainMenu = Menu.buildFromTemplate(mainMenuTemplate);
  // Insert menu
  Menu.setApplicationMenu(mainMenu);
});

// Handle create worker window
function createWorkerWindow() {
  mainWindow.webContents.send('status:showLoading'); // This does NOT work
  // Create new window
  workerWindow = new BrowserWindow({
    width: 300,
    height: 200,
    title: 'workerWindow',
    show: process.env.NODE_ENV == 'production' ? false : true
  });
  // Load the HTML file into the window
  workerWindow.loadURL(url.format({
    pathname: path.join(__dirname, 'worker.html'),
    protocol: 'file',
    slashes: true
  }));
  // Garbage collection
  workerWindow.on('close', function () {
    workerWindow = null;
  })
  mainWindow.webContents.send('status:hideLoading'); // This does NOT work
}

// Catch item:add-worker
ipcMain.on('item:add-worker', function(e, item){
  console.log(item);
  mainWindow.webContents.send('item:add-worker', item);
  workerWindow.close();
});


// Create menu template
const mainMenuTemplate = [{
  label: 'File',
  submenu: [
    {
      label: 'Add Item from Worker',
      click() {
        mainWindow.webContents.send('status:showLoading'); // This does NOT work
        createWorkerWindow();      
      }
    },
    {
      label: 'Clear Items',
      click(){
        mainWindow.webContents.send('item:clear'); // This works
      }
    },
    {
      label: 'Show Loading',
      click(){
        mainWindow.webContents.send('status:showLoading'); // This works
      }
    },
    {
      label: 'Hide Loading',
      click(){
        mainWindow.webContents.send('status:hideLoading') // This works
      }
    },
    {
      label: 'Quit',
      accelerator: process.platform == 'darwin' ? 'Command+Q' : 'Ctrl+Q',
      click() {
        app.quit();
      }
    }
  ]
}];

When I use the Show Loading and Hide Loading menu items, the main window receives the message and does what it needs to do. However, when I click the Add Item from Worker menu item, the message appears to not reach the main window.

 <!-- mainWindow.html --> <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Content-Security-Policy" content="default-src file: https:"> <title>Shopping List</title> <!-- Compiled and minified CSS --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/css/materialize.min.css"> <link rel="stylesheet" href="mainWindow.css"> </head> <body> <nav> <div class="nav-wrapper"> <a class="brand-logo center">Shopping List</a> <div id="loadingIndicator" class="progress"> <div class="indeterminate"></div> </div> </div> </nav> <ul></ul> <script src="mainWindow.js"></script> </body> </html> 

//// mainWindow.js

// Show Loading
ipcRenderer.on('status:showLoading', function(){
    document.getElementById('loadingIndicator').style.display = 'block';
}); 

// Hide Loading
ipcRenderer.on('status:hideLoading', function(){
    document.getElementById('loadingIndicator').style.display = 'none';
});

I tried to add the mainWindow.webContents.send('status:showLoading'); line in side the click() function for the menu item and inside the createWorkerWindow() function. Neither appear to work.

Any insight would be much appreciated.

Thank you.

The problem is that loading a url in a browser window isn't synchronous so when it runs createWorkerWindow it will send the status:showLoading message then it'll create the worker window and send the status:hideLoading all in a split second. If you wanted to hide the loading window after the worker window has finished loading you can use:

workerWindow.webContents.on('did-finish-load', function () {
    mainWindow.webContents.send('status:hideLoading');
});

Although keep in mind this will run when any url is loaded not just the first one.

did-finish-load docs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM