Межпроцессное взаимодействие (IPC) в ElectronJS
ElectronJS используется для создания кроссплатформенных приложений Native Desktop с использованием веб-технологий, таких как HTML , CSS и JavaScript, которые могут работать в операционных системах Windows, macOS и Linux. Он объединяет движок Chromium и NodeJS в единую среду выполнения. Несколько известных проектов с открытым исходным кодом, таких как Visual Studio Code, Slack, Atom, Postman и Brave Browser, разработаны с использованием Electron.
Электрон можно разделить на два основных процесса:
- Основной процесс
- Процесс рендеринга
IPC в Electron: один главный процесс может иметь несколько процессов рендеринга. Каждый процесс рендеринга можно рассматривать как новую вкладку в браузере. В этом руководстве мы обсудим, как Electron взаимодействует между этими процессами с помощью межпроцессного взаимодействия (IPC) . Electron предоставляет нам два модуля IPC для связи между процессами,
- ipcMain: этот модуль используется для обмена данными между основным процессом и процессами рендеринга. Он определен и используется в основном процессе. Он обрабатывает все синхронные и асинхронные сообщения, отправляемые процессом рендеринга.
- ipcRenderer: этот модуль используется для связи процессов рендерера с основным процессом. Он определен и используется в процессах рендеринга. Он предоставляет возможность отправлять сообщения и получать сообщения от основного процесса, синхронно и асинхронно.
Настоятельно рекомендуется не выполнять тяжелые вычисления в процессах рендеринга, чтобы приложение не замедлилось в производительности и не стало более ресурсоемким. Вместо этого мы должны использовать IPC для распределения этих задач по основному процессу и позволить главному процессу обрабатывать любые тяжелые вычисления в приложении. Между синхронной передачей данных и асинхронной передачей данных в IPC есть три основных различия:
- Метод ipc.send () используется для асинхронной передачи данных, тогда как для синхронной передачи данных вместо него используется метод ipc.sendSync ().
- Нам нужно специально реализовать функцию обратного вызова для обработки ответа, поступающего от основного процесса при асинхронной передаче данных. В случае синхронной передачи данных нам не нужно реализовывать функцию обратного вызова, поскольку метод ipc.sendSync () вернет данные.
- В Основной процесс (файл main.js), метод win.webContents.send () используется для асинхронной передачи данных. Его можно заменить методом event.returnValue () для синхронной передачи данных.
Примечание. В этом руководстве также предполагается, что вы знакомы с предварительными условиями, описанными в вышеупомянутой ссылке.
Структура проекта: начнем со строительных блоков Учебника,
- Шаг 1. Проверьте, установлены ли node и npm . Если нет, то посетите следующие разделы:
- Установка Node.js в Windows
- Установка Node.js в Linux
- Шаг 2: перейдите в пустой каталог, чтобы настроить проект, и выполните следующую команду,
npm init
Следуйте инструкциям по созданию файла package.json.
- Шаг 3: Убедитесь, что Electron установлен, если нет, то установите его сейчас.
- Шаг 4: Создайте файл main.js в соответствии со структурой проекта. Этот файл является основным процессом и действует как точка входа в приложение.
const { app, BrowserWindow } = require(
'electron'
)
let win;
function
createWindow() {
// Create the browser window.
win =
new
BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration:
true
}
})
// and load the index.html of the app.
win.loadFile(
'src/index.html'
)
// Open the DevTools.
// win.webContents.openDevTools()
//Quit app when main BrowserWindow Instance is closed
win.on(
'closed'
,
function
() {
app.quit();
});
}
// This method will be called when the Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)
// Quit when all windows are closed.
app.on(
'window-all-closed'
, () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if
(process.platform !==
'darwin'
) {
app.quit()
}
})
app.on(
'activate'
, () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if
(BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
- Шаг 5: Создайте файл index.html в каталоге src. Index.html отображается в отдельном процессе файлом main.js при запуске приложения. Каждый процесс рендеринга также может иметь свой собственный связанный файл CSS и JavaScript.
В index.html<!DOCTYPE html>
<
html
>
<
head
>
<
meta
charset
=
"UTF-8"
>
<
title
>Hello World!</
title
>
<
meta
http-equiv
=
"Content-Security-Policy"
content
=
"script-src 'self' 'unsafe-inline';"
/>
</
head
>
<
body
>
<
h1
>Hello Geeks!</
h1
>
<
div
>
We are using node
<
script
>
document.write(process.versions.node)
</
script
>, Chrome
<
script
>
document.write(process.versions.chrome)
</
script
>, and Electron
<
script
>
document.write(process.versions.electron)
</
script
>.
</
div
>
<
script
src
=
"index.js"
></
script
>
</
body
>
</
html
>
- Шаг 6: Чтобы запустить приложение Electron, запустите команду, «start» - это сценарий, который мы определили в файле package.json.
npm start
- Выход:
Асинхронная передача данных: поскольку мы настроили приложение Basic Electron, давайте определим новый BrowserWindow
который будет отображать новую веб-страницу. Эта новая веб-страница будет файлом new-window.html. Затем мы реализуем асинхронный IPC для обмена данными между файлом new-window.html и файлом index.html .
<!DOCTYPE html> < html lang = "en" > < head > < meta charset = "UTF-8" > < title >New Window</ title > < meta http-equiv = "Content-Security-Policy" content = "script-src 'self' 'unsafe-inline';" /> </ head > < body > < div >New Window Opened !</ div > < br > < input type = "text" > < button id = "submit" >Pass Value to Main Window</ button > < script src = "new-window.js" ></ script > </ body > </ html > |
script
< h3 >Aynschronous Message Sending</ h3 > < div > Value Received From Renderer Process - < span id = "value" ></ span > </ div > < br > < button id = "new" > Click Me to Open New Window </ button > |
const electron = require( 'electron' ) const path = require( 'path' ) // BrowserWindow Instance is a part of the Main Process, // To fetch its instance from the Main Process, // Use electron.remote const BrowserWindow = electron.remote.BrowserWindow var update = document.getElementById( 'value' ); var button = document.getElementById( 'new' ); button.addEventListener( 'click' , function (event) { // Linking to new-window.html let win = new BrowserWindow({ // To display the Default Frame of the Window // consisting of default Menu frame: true , // Makes the Renderer Window Sticky, // Will always stay on top despite focus change alwaysOnTop: true , width: 600, height: 400, webPreferences: { nodeIntegration: true } }); // Destroy the BrowserWindow Instance on close win.on( 'close' , function () { win = null ; }); // win.webContents.openDevTools(); win.loadURL(newPath); win.show(); }); |
Чтобы передать данные из тега «input» в new-window.html в index.html с помощью асинхронного IPC, выполните следующие действия:
- Шаг 1. В файле new-window.js
const electron = require(
'electron'
)
const remote = electron.remote;
// Import the ipcRenderer Module from Electron
const ipc = electron.ipcRenderer;
var
input = document.querySelector(
'input'
);
var
submit = document.getElementById(
'submit'
);
// Adding Click EventListener to the Button
submit.addEventListener(
'click'
,
function
() {
console.log(input.value);
// Calling the ipcRenderer.send()
// To send the value from the input tag with
// a Unique Key to the main process
// Asynchronously
ipc.send(
'update-value'
, input.value);
remote.getCurrentWindow().close();
});
- Шаг 2:
ipcMain
модуль ipcMain из файла main.js в файл main.js.const ipcMain = require ('электрон'). ipcMain
Добавьте в конец файла следующее:
// Responsible for Communication of data from Main
// process to the Renderer Process
// Received the value send from the new-window.js file
// Identifies the data passed based on the Key
// Which was set in the ipc.send() method in new-window.js file
ipcMain.on(
'update-value'
,
function
(event, arg) {
console.log(arg);
// Passing the data from Main Process to index.html
// BrowserWindow Instance, value will be received in
// the index.js based on the Key set here. Using the
// 'win.webContents.send' method for Asynchronous Data Transfer
win.webContents.send(
'updateValue'
, arg);
});
- Шаг 3.
ipcRenderer
модуль ipcRenderer из файла index.js в файл.const ipc = electronic.ipcRenderer;
Добавьте в конец файла следующее:
// Using the ipcRenderer.on() method
// Implementing the Callback Function for Asynchronous IPC,
// To receive the data based on the key set in the main.js file
ipc.on(
'updateValue'
,
function
(event, arg) {
console.log(arg);
// Updating the value of the HTML Tag with the Data Received
// In Case the Data Received is not a Number and is
// some arbitary Value,display will show as NaN (Not a Number)
update.innerHTML = Number(arg);
});
- Результат: мы успешно реализовали асинхронный IPC.
Синхронная передача данных: теперь мы реализуем синхронный IPC между основным процессом и процессом рендеринга и визуализируем различия между ними, как описано выше.
- Шаг 1. В файле index.html добавьте следующий код сразу после тега кнопки и перед тегом скрипта.
<
br
>
<
h3
>Synchronous Message Sending</
h3
>
<
div
>Value Received From Main Process -
<
span
id
=
"received"
></
span
>
</
div
>
<
br
>
<
button
id
=
"send"
>
Click Me for Synchronous Message
</
button
>
- Шаг 2. Кнопка «Щелкните меня, чтобы получить синхронное сообщение» не имеет связанных с ней функций. Мы добавим
EventListener
к кнопке, добавив следующий код в файл index.js.var
received = document.getElementById(
'received'
)
var
button2 = document.getElementById(
'send'
);
// Adding Click EventListener to button2
// For Synchronous Message Transfer we are using the 'ipc.sendSync' method
// We do not need to Implemented any Callbacks to handle the Response
// The 'ipc.sendSync' method will return the data from the Main Process
button2.addEventListener(
'click'
,
function
(event) {
// Setting the Key and the Message to be sent to the Main Process
const data = ipc.sendSync(
'synchronous'
,
'Message to Main Window'
);
// Setting the Data received to the <span> tag
received.innerHTML = data;
});
- Шаг 3. В файле main.js добавьте следующий код в конец файла:
ipcMain.on(
'synchronous'
, (event, arg) => {
// Using this method instead of 'win.webContents.send'
// for Synchronous Message Transfer
// The Value of arg = 'Message to Main Window'
// In case we do not use 'event.returnValue', We will
// get the following Error
// 'Uncaught Error: Unable to deserialize cloned data due to
// invalid or unsupported version.'
event.returnValue =
'Synchronous Message Sent'
;
});
- Выход: