Не удается обновить представление с помощью наблюдаемых с привязкой ngClass

У меня есть приложение Electron/Angular, которое запускает внешние приложения, и я отслеживаю, работают ли эти службы или нет, и показываю зеленые/красные индикаторы в нижнем колонтитуле, чтобы указать на это. Я использую API-интерфейс Electron IPC для передачи статуса устройств от Electron до Angular. Все это работает, и я получаю события, которые могу слушать в Angular.

У меня есть служба, которая прослушивает обновления статуса IPC

this.electronService.ipcRenderer.on(IpcChannels.SERVICE_STATUSES_UPDATE, (event, { deviceStatus }) => {
  // sending the new values through a private subject. There is a public
  // observable for the subject which consumers use. This works, i
  // receive updates when the services are stopped/started
  this.deviceStatus.next(deviceStatus);
});

В моем шаблоне компонента

<span class="bottom-icon dot"
  [ngClass]="{'inactive': !(deviceStatusService.deviceStatus$ | async)}"></span>

<span>{{'FooterBar.deviceLabel' | translate}}</span>

Вот где это не удается. Класс никогда не обновляется, чтобы иметь «неактивный» класс. Я возился с ним несколько часов, прежде чем случайно обнаружил, что он действительно работает. Angular просто не перерисовывает и не получает изменений, я думаю, потому что я обнаружил, что с задержкой запуска служб, когда мое приложение делало сетевой запрос ПОСЛЕ того, как статус изменился, но до того, как он вернулся к исходному значению, тогда angular будет повторно отображать. и это действительно будет обновляться. Но затем, после перезапуска службы, она снова не будет обновляться, пока что-то еще не запустит обновление angular.

У меня нет стратегии обнаружения изменений OnPush. Я попытался внедрить ChangeDetectionRef и с файлом компонента, прослушивающим наблюдаемые, самостоятельно и запустившим detectChanges() в ChangeDetectionRef.

Если я добавлю это в свою службу при инициализации и просто вручную/случайно обновлю наблюдаемые, это на самом деле сработает мгновенно, но когда я снова переключаюсь на выдачу новых значений только из обработчика рендеринга ipc, это не так.

interval(5000)
  .subscribe(_ => {
    this.posPrintStatus.next(Math.random() > .5 ? true : false);
    this.cePosStatus.next(Math.random() > .5 ? true : false);
  });

Я не понимаю, является ли это программной проблемой или проблемой обнаружения угловых изменений, которую я не понимаю.

Если есть какой-либо другой код/контекст, который я могу предоставить, пожалуйста, дайте мне знать.


person kamcknig    schedule 03.11.2019    source источник


Ответы (1)


Ответ был довольно прост, но я никогда не сталкивался с этой проблемой и никогда не задумывался об этом.

Это произошло потому, что связь IPC происходила за пределами зоны Angular. Мне пришлось внедрить экземпляр NgZone в свою службу и использовать NgZone.run() для обновления наблюдаемых значений внутри угловой зоны.

person kamcknig    schedule 03.11.2019