electron 从IpcMain通信时,未检测到Angular 变化

qlvxas9a  于 2022-12-16  发布在  Electron
关注(0)|答案(3)|浏览(210)

我正在使用Angular / Electron构建一个应用程序。在一个Angular组件中,我有一个方法-handleData()-它定义了一个对象-只是简单的数组、字符串、数字等,没有异步调用或类似的任何东西。然后,这个对象的属性用于使用*ngFor*ngIf创建和填充模板。
在开发过程中,我在组件中有一个按钮,当点击它时,它会直接调用handleData(),一切都很好-数据被创建,模板更新以反映它。有了这样的设置,我做了一个简单的更改,以便 * 现在 * 点击按钮通过IpcRenderer发送消息(使用this article中描述的IpcService)...

onButtonClick(){
   this.ipc.on('test-response', (e)=>{
      this.handleData();
   });
   this.ipc.send('test-channel');
}

这是在我的main.js中拾取的,我对此做出响应,发送回一条消息...

ipcMain.on('test-channel', (e)=>{
   e.sender.send('test-response');
});

在这种情况下,handleData()仍然被调用但是现在UI不再更新。每当我更新通过*ngIf*ngFor链接到模板的属性时,我必须使用ChangeDetectorRef并手动调用detectChanges
所以我的问题是,在IPC回调上调用方法与直接调用方法有什么不同?
这是同步/异步问题吗?区域问题?范围问题?
任何想法都乐意接受。
干杯

biswetbf

biswetbf1#

我使用NgZone修复了这个问题。如前所述,我本可以使用ChangeDetectorRef.detectChanges,但我不得不在每次更新后调用它,不仅在我的主组件中,而且在它的所有后代中,这似乎是错误的。
我读了一些文章,认为这可能是一个区域问题,所以我不得不最终尝试了解什么是区域。我发现this article and the links within it对获得基本的理解非常有帮助。
最后,我将NgZone注入到组件中:

constructor(private zone:NgZone){}

然后确保回调在Angular 区域中运行:

onButtonClicked(){
   this.ipc.on('test-response', (e)=>{
   this.zone.run(()=>{
      this.testFunc()
   });
});
this.ipc.send('test-channel');

我不会假装我确切地理解为什么会出现这个问题,或者为什么这个问题会得到解决,我假设使用Electron shell和IpcMain会将进程移出Angular 区域,而不会回到回调中。

vsikbqxv

vsikbqxv2#

使用变化探测器即可。

constructor(private cdr:ChangeDetectorRef)

onButtonClick(){
   this.ipc.on('test-response', (e)=>{
      this.handleData();
      this.cdr.detectChanges();
   });
   this.ipc.send('test-channel');
}

Angular 行程变化检测:
1.用户交互(点击、按键事件)
1.对@Input进行了更改
1.将发送更改为@Output
1.对公共组件变量所做的更改
记住,所有这些改变必须包括引用的改变,而不是值的内部状态的改变。
例如

public user:User;

public someMethod(){
   this.user=new User(); // this will trigger change detection run
   this.user.name="Sebastian"; // this will not, 
   this.cdr.detectChanges(); // hey Angular, I made some changes - update view for me
}
4jb9z9bj

4jb9z9bj3#

我也遇到过同样的问题,我通过处理同步事件处理解决了它。
在main.js中:
ipcMain.on('事件名称',(错误,参数)=〉{
event.returnValue = '要返回的值'
})
在浏览器文件中:
let result = ipcRenderer.. sendSync('事件名称','要发送任何值')
//结果包含来自main.js的回调值

相关问题