#javascript #typescript #browser #electron #ipc
#javascript #typescript #браузер #electron #ipc
Вопрос:
У меня есть приложение Electron с включенным в процесс рендеринга ReactJS и вспомогательной инфраструктурой, которая подключается и синхронизирует все хранилища во всех открытых процессах приложения (один основной процесс и несколько процессов рендеринга)
Связь Redux sync реализована через IPCS electron, поэтому у меня есть пара прослушивателей для разных каналов, эти прослушиватели добавляются для каждого процесса рендеринга (окно браузера)
в качестве примера, вот код, который прослушивает отправленные действия из основного процесса:
export const listenToFromMainDispatchedActions = (store: Store, senderId: string): () => void => {
const listener = (event: IpcRendererEvent, args: any): void => {
if (!isValidAppAction(args)) {
appLogger.warn('Received an invalid action form main!!!');
} else {
const action: IAppReduxAction<any> = {
...args,
meta: {
...args.meta,
handler: ReduxActionHandler.RECEIVER,
},
};
if (action.meta.senderId !== senderId) store.dispatch(action);
}
};
ipcRenderer.on(IPCChannels.ACTION_DISPATCH, listener);
appLogger.warn('STORE_DISPATCH', 'ADDED ACTION_DISPATCH');
return (): void => {
ipcRenderer.removeListener(IPCChannels.ACTION_DISPATCH, listener);
appLogger.warn('STORE_DISPATCH', 'REMOVED ACTION_DISPATCH');
};
};
этот фрагмент кода выполняется в моем index.tsx
файле следующим образом:
// index.tsx
// ...
export const GLOBAL_SENDER_ID = uuidV4();
const store = storeCreator({
level: 'renderer',
reducer: renderersReducer,
sagas: mainAppWindowSagas,
senderId: GLOBAL_SENDER_ID,
});
const listenerRemover = listenToFromMainDispatchedActions(store, GLOBAL_SENDER_ID);
...
Мой вопрос в том, как и когда лучше всего вызвать listenerRemover()
, чтобы удалить прослушиватель IPC?
Я пытался перехватить различные события документа / окна, такие как beforeunload
и подобные, но безрезультатно. Чтобы все было «гладко», я на самом деле открываю необходимые окна при запуске приложения и скрываю их, закрытие windows скрывает их вместо того, чтобы убивать их, я понимаю, что это проблематично с точки зрения событий, но мне нужен способ изящно удалить эти прослушиватели, я не нашел ничего полезного в документах
Заранее спасибо
Ответ №1:
Итак, решение, которое я придумал, заключается в следующем:
на стороне браузера / процесс рендеринга (в index.tsx
) я делаю следующее:
// index.tsx (renderer process)
// ...
export const GLOBAL_SENDER_ID = uuidV4();
const store = storeCreator({
level: 'renderer',
reducer: renderersReducer,
sagas: mainAppWindowSagas,
senderId: GLOBAL_SENDER_ID,
});
const listenerRemover = listenToFromMainDispatchedActions(store, GLOBAL_SENDER_ID);
const cleanup = (): void => {
appLogger.log('WINDOW CLOSING');
listenerRemover();
window.removeEventListener('beforeunload', cleanup);
}
window.addEventListener('beforeunload', cleanup)
...
и в основном процессе я удаляю все аналоги ipcMain:
// index.ts
import { app, ipcMain } from 'electron';
import main from './main'
// ....
app.whenReady()
.then(main)
.catch((error) => {
appLogger.error(TAG, error);
});
// .....
app.on('before-quit', () => {
Object.values(IPCChannels).forEach(
(channel) => {
ipcMain.removeAllListeners(channel);
}
);
appLogger.log('CLEANED ALL IPCS');
appLogger.log('Done, BYEBYE');
});
Кажется, он работает так, как ожидалось, и мне удается просмотреть журналы в соответствующих местах, хотя я не совсем уверен в правильности этого подхода, я оставлю свой вопрос без ответа на пару дней (сегодня 13.08.2020 12: 15 по восточному времени).
Если я не получу никаких других / лучших ответов через неделю или около того, я приму свой ответ как правильный.
Комментарии:
1. Принял мой собственный ответ, поскольку не было других более эффективных решений, сегодня 21.08.2020 15: 53 CEST