Electron Renderer 进程:我应该什么时候清理 IPC 监听器
Electron Renderer Process: When Should I Clean IPC Listeners
我有一个 Electron 应用程序,在渲染器进程 ReactJs 和 Redux 基础设施上连接并同步应用程序所有打开进程(一个主进程和多个渲染器进程)中的所有商店
Redux 同步通信是通过电子 IPC 实现的,所以我有几个针对不同通道的侦听器,这些侦听器是为每个渲染器进程添加的(浏览器 window)
举个例子,下面是监听主进程调度动作的代码:
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 侦听器的最佳方式?
我尝试捕捉不同的 document/window 事件,例如 beforeunload
等,但无济于事。
为了保持一切“顺利”,我实际上在应用程序启动时打开所需的 windows 并隐藏它们,关闭 windows 隐藏它们而不是杀死它们,我意识到这是明智的问题事件,但我需要一种优雅地删除这些侦听器的方法,我在文档中没有发现任何有用的东西
提前致谢
所以我想到的解决方案如下:
在浏览器 side/renderer 进程中(在 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:15CEST).
如果我在一周左右的时间内没有得到任何 other/better 个答案,我会接受我的答案作为正确答案。
我有一个 Electron 应用程序,在渲染器进程 ReactJs 和 Redux 基础设施上连接并同步应用程序所有打开进程(一个主进程和多个渲染器进程)中的所有商店
Redux 同步通信是通过电子 IPC 实现的,所以我有几个针对不同通道的侦听器,这些侦听器是为每个渲染器进程添加的(浏览器 window)
举个例子,下面是监听主进程调度动作的代码:
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 侦听器的最佳方式?
我尝试捕捉不同的 document/window 事件,例如 beforeunload
等,但无济于事。
为了保持一切“顺利”,我实际上在应用程序启动时打开所需的 windows 并隐藏它们,关闭 windows 隐藏它们而不是杀死它们,我意识到这是明智的问题事件,但我需要一种优雅地删除这些侦听器的方法,我在文档中没有发现任何有用的东西
提前致谢
所以我想到的解决方案如下:
在浏览器 side/renderer 进程中(在 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:15CEST).
如果我在一周左右的时间内没有得到任何 other/better 个答案,我会接受我的答案作为正确答案。