Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

IPC: от страницы к главному процессу

IPC — обмен сообщениями между процессами. Самый частый случай: странице нужно, чтобы главный процесс что-то сделал и вернул результат, например прочитал заметки. Для этого главный процесс регистрирует обработчик через ipcMain.handle, а страница вызывает его через ipcRenderer.invoke и получает промис с ответом.

Обработчик в главном процессе

Сообщения различаются по имени канала — обычной строке. Принято писать её как тема:действие. Добавьте в main.js:

// main.js
const { app, BrowserWindow, ipcMain } = require('electron');
 
let notes = ['Купить хлеб', 'Позвонить Анне'];
 
app.whenReady().then(() => {
  ipcMain.handle('notes:load', () => {
    return notes;
  });
 
  createWindow();
});

Функция-обработчик вызывается на каждый запрос по каналу notes:load. То, что она вернёт, получит страница. Пока заметки хранятся в памяти главного процесса.

Мост в preload

Страница не видит ipcRenderer, поэтому preload передаёт ей функцию-обёртку:

// preload.js
const { contextBridge, ipcRenderer } = require('electron');
 
contextBridge.exposeInMainWorld('notes', {
  load: () => ipcRenderer.invoke('notes:load'),
});

invoke отправляет запрос и возвращает промис, который выполнится ответом обработчика.

Вызов со страницы

// renderer.js
const list = document.querySelector('#notes');
 
async function showNotes() {
  const notes = await window.notes.load();
  list.replaceChildren();
  for (const note of notes) {
    const li = document.createElement('li');
    li.textContent = note;
    list.append(li);
  }
}
 
showNotes();

После запуска в окне появятся две заметки из главного процесса.

Передача данных

Аргументы invoke приходят в обработчик после объекта события:

// main.js
ipcMain.handle('notes:add', (event, text) => {
  notes.push(text);
  return notes;
});
// preload.js
contextBridge.exposeInMainWorld('notes', {
  load: () => ipcRenderer.invoke('notes:load'),
  add: (text) => ipcRenderer.invoke('notes:add', text),
});

На странице форма вызывает await window.notes.add(text.value) и затем showNotes(). Данные передаются копией: строки, числа, массивы и простые объекты проходят, а функции и элементы DOM — нет.

Ошибки

Если обработчик выбросит ошибку, промис на странице будет отклонён:

// main.js
ipcMain.handle('notes:add', (event, text) => {
  if (text.trim() === '') {
    throw new Error('Пустая заметка');
  }
  notes.push(text);
  return notes;
});

На странице такой вызов оборачивают в try...catch и показывают сообщение пользователю.

Частая ошибка

Если вызвать ipcMain.handle внутри createWindow, то при повторном создании окна (например, по событию activate в macOS) Electron выбросит ошибку Attempted to register a second handler for 'notes:load'. Обработчик на канал можно зарегистрировать только один раз — делайте это один раз после whenReady, вне функции создания окна.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.