从电子容器IPC通道接收数据时,变更检测会间歇性地工作

Kod*_*_12 10 javascript ipc electron angular2-changedetection angular

我有一个正在侦听来自IPC渲染器通道的​​传入数据的应用程序。这是我的设置:

将数据发送到角度应用程序(mainWindow)的容器:

mainWindow.loadURL('http://www.myangularapp.com') //where the angular app lives (example url).
mainWindow.webContents.on('did-finish-load', () => {
      const data = { name: "John Doe", address: "123 Main St", city: "NY"}
      mainWindow.webContents.send('data-from-container', data)
        }
    })
Run Code Online (Sandbox Code Playgroud)

角度应用:

constructor(
    private store: Store<fromStore.AppState>,
    private cd: ChangeDetectorRef,
    private zone: NgZone,
  ) {}

  ngOnInit() {
this.isLoading = true;
    if (this.electronService.ipcRenderer) {
      this.electronService.ipcRenderer.on('data-from-container', (event, data) => {
        this.zone.run(() => {
          if(data){
            setTimeout(() => {
              console.log(data) // verified data is always received
              this.formData = data; // property that form uses to populate data in the dom
              this.prepopulateForm(data) // method that places incoming data in ngrx store
            }, 1000)
          }
        })
      })
    }

    this.store.select('containerData').subscribe(data => {
        setTimeout(()=> {
          console.log(data) // data is always being set in ngrx
          this.isLoading = false
        }, 5000);
    })

  }
Run Code Online (Sandbox Code Playgroud)

每当IPC通道发出“来自容器的数据”事件时,总是从我的OnInit调用中接收数据,但是并不总是以我的形式设置数据!我注意到的模式通常是,当有角度的应用程序首次在容器内启动时,数据不会预先填充表格,在初始启动后,每当应用程序每次启动时,数据就会出现。

我尝试使用ngZone,setTimeout和detectChange方法来触发更改检测,以便Angular App可以检测到新设置的formData,但它并不能始终如一地预填充表单。对于如何解决这个问题,有任何的建议吗?

bub*_*les 3

我对电子有非常基本的了解,所以我会尽力向您展示这个想法。对我来说,你的问题来自视图的初始化。您不会丢失事件,因为您可以在控制台中看到它们,但不能在视图中看到它们,这强化了我的猜测。

如您的代码所示,您仅发送一个事件(我想这只是为了测试存在的理由),我们希望在渲染视图时显示它。

在您的组件中添加一个主题,通知我们视图已初始化,例如:

import { Subject, combineLatest, fromEvent } from 'rxjs';

viewInitialized$ = new Subject();

...

ngAfterViewInit() {
 this.viewInitialized$.next();
}

...
Run Code Online (Sandbox Code Playgroud)

现在我们可以等待两个排放的到来,一个来自ipcRenderer,另一个来自viewInitialized$使用combineLatest运算符。

在此之前,我们必须将 转换ipcRendererObservable. 从这个SO响应我们可以做fromEvent(ipcRenderer,'data-from-container')。如果它不起作用,我们可以使用另一个主题,每次我们收到 中的内容时都会发出事件ipcRenderer.on(),第二个解决方案需要 ngZone。


ngOnInit() {
...

const containerData$ = fromEvent(this.electronService.ipcRenderer, 'data-from-container');
this.subscription = combineLatest(containerData$, this.viewInitialized$).subscribe(combined => {
  const data = combined[0];
  this.formData = data;
  this.prepopulateForm(data) 
})

...
}

ngOnDestroy() {
  this.subscription.unsubscribe();
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。