【问题标题】:Using ipcRenderer in angular 2; trigger change detection在角度 2 中使用 ipcRenderer;触发变化检测
【发布时间】:2017-03-12 21:26:01
【问题描述】:

我正在渲染器进程中构建一个角度为 2 的电子应用程序。我的主要进程与套接字服务器通信。每当用户连接到此服务器或断开连接时,我希望在视图中显示用户的状态。

为此,我使用 electron 的 ipc 将消息从主进程发送到渲染器进程,如下所示

socket.on('connect', function() {
  mainWindow.webContents.send('socket-connection-status', true);
});
socket.on('disconnect', function() {
  mainWindow.webContents.send('socket-connection-status', false);
});

在我看来,我有一个(简化的)角度组件,像这样

const ipc = require('electron').ipcRenderer;
@Component({
  selector: 'status-bar',
  template: '{{status}}'
})
export class StatusBarComponent {
  private status: string = "offline";
  constructor() {
    ipc.on('socket-connection-status', function(event, status) {
      if (status===true) {
        this.status = 'online';
      } else {
        this.status = 'offline';
      }
      console.log(status);  // Successfully logs true|false
      console.log(this.status);  // Successfully logs online|offline
    })
  }
}

我成功记录了来自主进程的消息。

问题是 angular 2 不“知道”电子的 ipc,因此status 不会触发更改检测。我见过几个人在这个问题上苦苦挣扎,但还没有找到一个“真正的”解决方案。

我尝试通过注入ApplicationRefChangeDetectorRefngZone(参考:Triggering Angular2 change detection manually)来解决它,但没有提供任何方法(分别为tick()detectChanges()run())碰巧提供了一个解决方案。

显然,“在”ipc.on 内,当我遇到错误时,我无法引用我的类的属性/方法/可注射:例如,这个 (https://github.com/JGantner/angular2_change_detection_issue/blob/master/browser/security-level-indicator-component.ts) 解决方案(我觉得不是很优雅)导致 @987654333 @。

有人可以帮我解决如何在我的情况下进行变更检测吗?


编辑(破解):

我找到了一种至少获得我需要/想要的功能的方法:

status-bar.component.ts:

const ipc = require('electron').ipcRenderer;
import { SocketStatusService } from '../services/socket-status.service';
@Component({
  selector: 'status-bar',
  template: '{{status}}'
})
export class StatusBarComponent {
  private status: string = "offline";
  status$: Subscription;
  constructor(private socketStatusService: SocketStatusService, private ref: ApplicationRef) {
  ipc.on('socket-connection-status', function(evt, status) {
    if (status===true) {
      this.service.updateSocketStatus('online');
    } else {
      this.service.updateSocketStatus('offline');
    }
  }.bind({service: socketStatusService}))

  this.status$ = this.socketStatusService.socket_status$.subscribe(
    status => {
      this.status = status;
      this.ref.tick();
    }
  )
}

socket-status.service.ts:

@Injectable()
export class SocketStatusService {
  private socket_status = new BehaviorSubject<string>("offline");
  socket_status$ = this.socket_status.asObservable();

  updateSocketStatus(status: string) { 
    this.socket_status.next(status);
  }
}

虽然这可行,但我觉得必须有一种更优雅的方式来实现这种行为。

虽然最好的情况是直接在 ipc 回调中设置组件的类属性并触发更改检测......到目前为止,我还无法让它工作,所以任何帮助将不胜感激。

(ps 另外,我不知道为什么我必须手动触发this.ref.tick(),这不是我记得在 angular 2 的早期 beta 版本中触发变化检测时必须做的事情......)

【问题讨论】:

  • 更改检测可能会通过使用setTimeout 包装代码来触发。 markForCheck 不起作用,因为事件处理程序不是箭头,因此 this 不是词法,这是一个常见的错误。您尝试过的其他方法(tick()detectChanges()run())是否有同样的问题?
  • 是的,我在ipc.on(,...) 中注入和引用的任何内容都会引发问题。例如,我认为也许创建一个状态为 BehaviorSubject 的服务然后订阅它可能会帮助我。但在那种情况下,我也会得到TypeError: Cannot read property 'updateSocketStatus' of undefinedupdateSocketStatus 是向下游发送新值的方法。所以基本上我的问题是如何处理从主服务器发送到渲染器的一般数据......this.statusipc.on 中记录正确的值(如在帖子中),但在它之外,它仍然是offline .
  • 如果你刚刚设置了this.status,那么肯定会在你登录this.status时设置。问题是它将被设置在错误的对象上。
  • 好的,我找到了一个“中间”解决方案。 TypeError 问题似乎是范围问题;我必须将我的实例绑定到回调,即ipc.on('...', (evt, status)=&gt;{...}.bind({service: socketStatusService})),然后在回调中使用this.service。像这样我可以使用一个服务来广播,然后我可以观察并触发变化检测。最终的解决方案是能够在回调中设置类属性并触发更改检测,而无需服务。我很想知道如何做到这一点。
  • 这里的服务对我来说是多余的。 ipc.on('...', (evt, status) =&gt; { ...; this.changeDetectorRef.detectChanges() })ipc.on('...', (evt, status) =&gt; setTimeout(() =&gt; { ... })) 不适合你吗?

标签: angular electron angular2-changedetection


【解决方案1】:

this.status 设置在错误的对象上,markForCheck 也因此不起作用。事件处理程序应该是一个箭头,以便提供正确的上下文。

使用适当的this 上下文,任何已知的触发更改检测的方法都应该有效。

例如

ipc.on('...', (evt, status) => {
  ...
  this.changeDetectorRef.detectChanges();
});

或者

ipc.on('...', (evt, status) => {
  setTimeout(() => {
    ...
  });
});

【讨论】:

  • 所以我的问题最终是使用function(evt, status){...} 语法进行回调,这会引发TypeError 未定义changeDetectorRef。我想NgZoneApplicationRef 的其他方法也应该能够像这样工作。
  • 没错。我想他们中的任何一个都会起作用。由于这个原因,在 TS 和 ES6 中,回调是必须的(包括事件处理程序、承诺回调和其他任何东西)。
猜你喜欢
  • 1970-01-01
  • 2018-06-28
  • 2017-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-23
  • 2021-06-17
相关资源
最近更新 更多