Electron - 限制从主进程到渲染进程的消息流
Posted
技术标签:
【中文标题】Electron - 限制从主进程到渲染进程的消息流【英文标题】:Electron - throttle flow of messages from main to render process 【发布时间】:2022-01-15 04:49:27 【问题描述】:我目前在接收从我的主进程到我的渲染器进程(在 Angular 中)的活动窗口的恒定流时遇到一些问题。我知道接收每秒更新会破坏我的应用程序,所以我试图使用 setTimeout 来限制它。但这仍然行不通。我该如何解决这个问题?
渲染器 - Angular 中的组件
ipc: IpcRenderer | undefined | null;
constructor(private electronService: ElectronService)
ngAfterViewInit(): void
this.getActiveWindow();
getActiveWindow()
while(this.electronService.isElectronApp)
this.ipc = this.electronService.ipcRenderer;
this.ipc.send('get-active-window');
this.ipc.on('get-active-window-reply', (_event, reply) =>
console.log(reply);
);
main.js
const activeWindows = require('electron-active-window');
ipcMain.on('get-active-window', (_event, _arg) =>
let i = 0;
setTimeout(function ()
activeWindows().getActiveWindow().then((result) =>
win.webContents.send("get-active-window-reply", result)
)
, 10000 * i)
);
到目前为止,我已经尝试了以下方法,但这只会显示一次活动窗口。我想跟踪所有的变化:
渲染器 - Angular 中的组件
ngOnInit(): void
this.getActiveWindow();
getActiveWindow()
if(this.electronService.isElectronApp)
this.ipc = this.electronService.ipcRenderer;
this.ipc.send('get-active-window');
this.ipc.on('get-active-window-reply', (_event, reply) =>
console.log(reply);
);
main.js
ipcMain.on('get-active-window', (_event, _arg) =>
activeWindows().getActiveWindow().then((result) =>
win.webContents.send("get-active-window-reply", result)
);
);
【问题讨论】:
这段代码有很多问题。您有一个 while 循环,它不断发送事件和注册处理程序。响应处理程序只是发送延迟响应。双方在本质上都有些异步。想想你当前的代码会发生什么以及你想要什么,然后尝试从那里重新工作。 @***soft 感谢您的回复。我已经更新了我的问题以显示我目前在哪里。第二次尝试似乎只获得一次窗口标题。我想让这个实时。我该如何解决这个问题? 【参考方案1】:您只收到一次活动窗口,因为您只在ngOnInit
中请求它们一次。
所以在我看来,您目前有两种选择。
-
您每隔几秒就向客户端请求一次信息
您让 Electron 应用程序通知客户端有关窗口的信息
选项 1:(仅解决方案 afaik)
render.component
import interval from 'rxjs';
...
getActiveWindow()
if(this.electronService.isElectronApp)
this.ipc = this.electronService.ipcRenderer;
this.ipc.on('get-active-window-reply', (_event, reply) =>
console.log(reply);
);
// A request directly to get "instant" feedback
this.ipc.send('get-active-window');
// You could also use setInterval but I prefer rxjs more ;)
// Don't forget to unsubscribe in ngOnDestroy
interval(2000).subscribe(() =>
this.ipc.send('get-active-window');
);
此解决方案会产生大量开销,因为您不需要每隔几秒更新活动窗口,因此我 不 推荐这个。
选项 2(推荐不起作用):
main.js
// Sends a message every time a BrowserWindow is created
app.on('browser-window-created', (event, window) =>
this.sendActiveWindows();
);
// Respond to the client request
ipcMain.on('get-active-window', (_event, _arg) =>
this.sendActiveWindows();
);
// Helper function
sendActiveWindows()
activeWindows().getActiveWindow().then((result) =>
win.webContents.send("get-active-window-reply", result)
);
如果您还需要关闭窗口时的信息,您需要向BrowserWindow.on('closed',...)
(更多here)添加一个侦听器,然后通知您的客户。
render.component.ts(仅添加 cmets)
getActiveWindow()
if(this.electronService.isElectronApp)
this.ipc = this.electronService.ipcRenderer;
// Request the currently active windows,
// otherwise this info is missing until new window is created
this.ipc.send('get-active-window');
this.ipc.on('get-active-window-reply', (_event, reply) =>
console.log(reply);
);
此解决方案更合适,因为您的客户只会在窗口数量发生变化时收到通知,所以我推荐这个
更新
在聊天中澄清问题后,您不能使用选项 2,因为您想检测操作系统的活动窗口而不是 Electron 应用程序的活动窗口。 由于信息 选项 1 是唯一有效的解决方案这里
【讨论】:
getActiveWindow 应该可能从区间返回 Observable,否则很好的解决方案! 这取决于你 ;) 你也可以将订阅分配给getActiveWindow
内部的一个变量,在这种情况下就没有必要了。谢谢:)
感谢@Batajus。我已经尝试了选项 2,但它似乎不起作用。我的 main.js 在pastebin.com/uV2b12Nm,我的组件代码在这里:pastebin.com/Ae4Bx0Pu。
选项 1 有效,但我在控制台中收到错误 (node:22168) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 get-active-window-reply listeners added to [EventEmitter]. Use emitter.setMaxListeners() to increase limit (Use
electron --trace-warnings ...` 以显示警告的创建位置)`,所以这可能不是一个好主意.
初始化程序时它会选择新窗口标题,但当我切换到另一个程序时它不会选择它,例如 Telegram。以上是关于Electron - 限制从主进程到渲染进程的消息流的主要内容,如果未能解决你的问题,请参考以下文章