5

レンダラー プロセスで angular 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
    })
  }
}

メインプロセスからのメッセージを正常にログに記録しました。

問題は、角度 2 が電子の ipc を「認識」していないため、変更検出がトリガーされないことですstatus。この問題に苦しんでいる人を何人か見てきましたが、「真の」解決策に出くわしていません。

ApplicationRefChangeDetectorRefおよびngZone(参照:手動で Angular2 変更検出をトリガーする )を注入して解決しようとしましたが、提供された方法 ( tick()detectChanges()run()それぞれ) のいずれもたまたま解決策を提供しませんでした。

どうやら、ipc.onエラーが発生したため、「内部」でクラスのプロパティ/メソッド/インジェクタブルを参照できません。 -component.ts ) ソリューション (あまりエレガントではないと思います) の結果はUncaught TypeError: Cannot read property 'markForCheck' of undefined.

私の場合、変更検出を機能させる方法を教えてください。


編集(ハック):

私が見つけた1つの方法で、少なくとも必要な/欲しい機能を取得できます:

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の以前のベータ版でストリームから変更検出をトリガーするために実行しなければならなかったことを覚えているものではありません...)

4

1 に答える 1

6

this.status間違ったオブジェクトに設定されているmarkForCheckため、これも機能しません。適切なコンテキストを提供するには、イベント ハンドラを矢印にする必要があります。

適切なthisコンテキストがあれば、変更検出をトリガーする既知の方法が機能するはずです。

例えば

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

または

ipc.on('...', (evt, status) => {
  setTimeout(() => {
    ...
  });
});
于 2016-10-30T23:23:54.070 に答える