Electron has two processes named IPC Main and IPC Renderer for sending data between each other.
IPC Renderer usually called from the web page. It sends a request to the IPC Main which processes data and gives a response back.
IPC Renderer -> IPC Main -> IPC Renderer
This way you can transfer data between window and main process.
Code
Code examples are available in Electron Documentation: ipcMain.
Main process
const { ipcMain } = require('electron');
/** Define channel name and message */
const CHANNEL_NAME = 'main';
const MESSAGE = 'pong';
/**
* SYNCHRONOUS
*/
ipcMain.on(CHANNEL_NAME, (event, data) => {
console.log(data); // show the request data
event.returnValue = MESSAGE; // send a response for a synchronous request
});
/**
* ASYNCHRONOUS
*/
ipcMain.on(CHANNEL_NAME, (event, data) => {
console.log(data); // show the request data
event.reply(CHANNEL_NAME, MESSAGE) // callback with a response for an asynchronous request
});
Web page
const { ipcRenderer } = require('electron');
/** Define channel name and message */
const CHANNEL_NAME = 'main';
const MESSAGE = 'ping';
/**
* SYNCHRONOUS
*/
console.log(ipcRenderer.sendSync(CHANNEL_NAME, MESSAGE)); // send request and show response
/**
* ASYNCHRONOUS
*/
ipcRenderer.send(CHANNEL_NAME, message); // send request
ipcRenderer.on(CHANNEL_NAME, (event, data) => { // IPC event listener
console.log(data); // show the response data
});
Examples
Here is a package.json
file for our sample Electron app.
{
"main": "main.js",
"scripts": {
"start": "electron ."
},
"devDependencies": {
"electron": "^5.0.1"
}
}
Create this file and run npm start
to install required packages.
Then create a main.js
script for the app.
const { app, BrowserWindow, ipcMain } = require('electron');
/**
* Create a new window
*/
const createWindow = () => {
let mainWindow = new BrowserWindow({
webPreferences: {
/** Enable node integration */
nodeIntegration: true
}
});
/** Open devTools */
mainWindow.webContents.openDevTools();
/** Load the index.html page */
mainWindow.loadFile('index.html');
};
/**
* Initialize the application
*/
const init = () => {
/** Create app window */
createWindow();
/** Define channel name */
const CHANNEL_NAME = 'main';
/**
* Add an IPC event listener for the channel
*/
ipcMain.on(CHANNEL_NAME, (event, data) => {
/** Show the request data */
console.log(data);
/** Send a response for a synchronous request */
event.returnValue = 'pong';
})
};
/**
* Run the app
*/
app.on('ready', init);
And the last file is an index.html
page.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>IPC test app</title>
<script>
const { ipcRenderer } = require('electron');
/** Define channel name */
const CHANNEL_NAME = 'main';
/** Create a processor for a button's click event */
const clickButton = () => {
/** Message to be sent */
let message = 'ping';
/** Show response for a sync IPC request */
console.log(ipcRenderer.sendSync(CHANNEL_NAME, message));
}
</script>
</head>
<body>
<button onclick="clickButton()">Press me</button>
</body>
</html>
Now you can run this Electron app by the simple command npm start
.
You will see a browser window with a one button on the page. Click it.
In the terminal with a running script ping
will be shown. Also pong
will be appeared in the browser's console.
Asynchronous requests
You can also send and process async requests.
Updated main.js
file.
const { app, BrowserWindow, ipcMain } = require('electron');
let mainWindow;
/**
* Create a new window
*/
const createWindow = () => {
mainWindow = new BrowserWindow({
webPreferences: {
/** Enable node integration */
nodeIntegration: true
}
});
/** Open devTools */
mainWindow.webContents.openDevTools();
/** Load the index.html page */
mainWindow.loadFile('index.html');
};
/**
* Initialize the application
*/
const init = () => {
/** Create app window */
createWindow();
/** Define channel name */
const CHANNEL_NAME = 'main';
/**
* Add an IPC event listener for the channel
*/
ipcMain.on(CHANNEL_NAME, (event, data) => {
/** Show the request data */
console.log(data);
/** Callback with a response for an asynchronous request */
event.reply(CHANNEL_NAME, 'pong')
})
};
/**
* Run the app
*/
app.on('ready', init);
Updated index.html
file.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>IPC test app</title>
<script>
const { ipcRenderer } = require('electron');
/** Define channel name */
const CHANNEL_NAME = 'main';
/** Add IPC event listener */
ipcRenderer.on(CHANNEL_NAME, (event, data) => {
console.log(data);
});
/** Create a processor for a button's click event */
const clickButton = () => {
/** Message to be sent */
let message = 'ping';
/** Send async request without waiting answer */
ipcRenderer.send(CHANNEL_NAME, message)
}
</script>
</head>
<body>
<button onclick="clickButton()">Press me</button>
</body>
</html>
ipcMain to ipcRenderer
You can send data from ipcMain to ipcRenderer manually without waiting for a response via send()
method of windows's content.
mainWindow
is an instance of a BrowserWindow
.
const CHANNEL_NAME = 'main';
const MESSAGE = 'tick';
setInterval(() => {
mainWindow.webContents.send(CHANNEL_NAME, MESSAGE);
}, 1000);
You can handle this event on the web page by ipcRenderer.
const CHANNEL_NAME = 'main';
ipcRenderer.on(CHANNEL_NAME, (event, data) => {
console.log(data);
});
Example
main.js
file.
const { app, BrowserWindow, ipcMain } = require('electron');
/** Define window's variable in the global scope */
let mainWindow;
/**
* Create a new window
*/
const createWindow = () => {
mainWindow = new BrowserWindow({
webPreferences: {
/** Enable node integration */
nodeIntegration: true
}
});
/** Open devTools */
mainWindow.webContents.openDevTools();
/** Load the index.html page */
mainWindow.loadFile('index.html');
};
/**
* Initialize the application
*/
const init = () => {
/** Create app window */
createWindow();
/** Define channel name and message */
const CHANNEL_NAME = 'main';
const MESSAGE = 'tick';
/** Send message every one second */
setInterval(() => {
mainWindow.webContents.send(CHANNEL_NAME, MESSAGE);
}, 1000);
};
/**
* Run the app
*/
app.on('ready', init);
index.html
file.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>IPC test app</title>
<script>
const { ipcRenderer } = require('electron');
/** Define channel name */
const CHANNEL_NAME = 'main';
/** Add IPC event listener */
ipcRenderer.on(CHANNEL_NAME, (event, data) => {
console.log(data);
});
</script>
</head>
<body>
</body>
</html>