Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Closing application and notifying renderer process

Tags:

electron

I have an Electron application that needs to save some data when it's closed by the user (e.g. just after the user clicked on the "Close" button).

The data is available at the renderer process, so it should be notified before the application dies.

The Electron API for Browser Window mentions a close method, but it seems this is done by the main process, not the renderer one (if I'm not mistaken).

I tried using WebContents.send from the main process to notify the renderer process, but it seems that, because the message is asynchronous, the application is closed before the renderer process has the time to actually perform the operations.

like image 879
anol Avatar asked Mar 18 '16 18:03

anol


3 Answers

You can just use the normal unload or beforeunload events in the renderer process:

window.addEventListener('unload', function(event) {
  // store data etc.
})
like image 174
flori Avatar answered Sep 28 '22 16:09

flori


So far, the simplest solution that worked for me consists in doing the following:

  1. On the main process, the BrowserWindow listens on the close event, and when it happens, it sends a message via webContents to the renderer process. It also prevents the application from being immediately closed by calling event.preventDefault();
  2. The renderer process is always listening on IPC messages from the main process, then when it receives the close event notification, it saves its data, then sends the main process an IPC message (e.g. closed);
  3. The main process has previously set a hook to listen to the renderer IPC messages (ipcMain.on), so when the closed message arrives, it finally closes the program (e.g. via app.quit()).

Note that, if I understood it correctly, calling app.quit() sends another close event to the BrowserWindow, so it will loop unless you prevent it somehow. I used a dirty hack (quit the second time the close event is called, without calling event.preventDefault()), but a better solution must exist.

like image 33
anol Avatar answered Sep 28 '22 17:09

anol


On the Main process:

    const ipc = require('electron').ipcMain;
    let status = 0;

    mainWindow.on('close', function (e) {
    if (status == 0) {
      if (mainWindow) {
        e.preventDefault();
        mainWindow.webContents.send('app-close');
      }
    }
  })

ipc.on('closed', _ => {
  status = 1;
  mainWindow = null;
  if (process.platform !== 'darwin') {
    app.quit();
  }
})

On the renderer process:

const electron = require('electron');
const ipc = electron.ipcRenderer;

ipc.on('app-close', _ => {

        //do something here...

        ipc.send('closed');
    });
like image 41
Clint Clinton Avatar answered Sep 28 '22 18:09

Clint Clinton