web-dev-qa-db-ja.com

Angular and rxjs?でwebsocketを再接続しますか?

オブザーバブルを使用して着信データのWebソケットをリッスンするngrx/store(v2.2.2)およびrxjs(v5.1.0)ベースのアプリケーションがあります。アプリケーションを起動すると、着信データを問題なく受信します。

ただし、しばらくすると(更新はめったに行われません)接続が失われたように見え、受信データがもう届きません。私のコード:

サービス

import { Injectable, OnInit } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable()
export class MemberService implements OnInit {

  private websocket: any;
  private destination: string = "wss://notessensei.mybluemix.net/ws/time";

  constructor() { }

  ngOnInit() { }

  listenToTheSocket(): Observable<any> {

    this.websocket = new WebSocket(this.destination);

    this.websocket.onopen = () => {
      console.log("WebService Connected to " + this.destination);
    }

    return Observable.create(observer => {
      this.websocket.onmessage = (evt) => {
        observer.next(evt);
      };
    })
      .map(res => res.data)
      .share();
  }
}

加入者

  export class AppComponent implements OnInit {

  constructor(/*private store: Store<fromRoot.State>,*/ private memberService: MemberService) {}

  ngOnInit() {
    this.memberService.listenToTheSocket().subscribe((result: any) => {
      try {
        console.log(result);
        // const member: any = JSON.parse(result);
        // this.store.dispatch(new MemberActions.AddMember(member));
      } catch (ex) {
        console.log(JSON.stringify(ex));
      }
    })
  }
}

タイムアウトしたときにWebソケットを再接続するために何をする必要がありますか?

私はいくつかのQ&Aを見ました herehere and here そしてこの質問に対処するようには見えませんでした)。

注:wss://notessensei.mybluemix.net/ws/timeのwebsocketはライブで、1分に1回タイムスタンプを発行します(テストする場合)。

アドバイスは大歓迎です!

12
stwissel

実際、rxjsにはWebsocketSubjectがあります!

 import { webSocket } from 'rxjs/webSocket' // for RxJS 6, for v5 use Observable.webSocket

 let subject = webSocket('ws://localhost:8081');
 subject.subscribe(
    (msg) => console.log('message received: ' + msg),
    (err) => console.log(err),
    () => console.log('complete')
  );
 subject.next(JSON.stringify({ op: 'hello' }));

切断された接続を再サブスクライブするときに、再接続を処理します。したがって、たとえば、これを書いて再接続します:

subject.retry().subscribe(...)

詳細については、ドキュメントを参照してください。残念ながら、検索ボックスにはメソッドは表示されませんが、ここで見つけることができます。

http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#static-method-webSocket

その#-navigationがブラウザで機能しないため、そのページで「webSocket」を検索してください。

ソース: http://reactivex.io/rxjs/file/es6/observable/dom/WebSocketSubject.js.html#lineNumber15

25
Herman

Rxjs 6の場合、websocket実装。

import { webSocket } from 'rxjs/websocket';
let subject = webSocket('ws://localhost:8081');
1
carkod

これは良い答えではないかもしれませんが、コメントするには多すぎます。

問題はあなたのサービスから来るかもしれません:

listenToTheSocket(): Observable<any> {
  this.websocket = new WebSocket(this.destination);

  this.websocket.onopen = () => {
    console.log("WebService Connected to " + this.destination);
  }

  return Observable.create(observer => {
    this.websocket.onmessage = (evt) => {
      observer.next(evt);
    };
  })
  .map(res => res.data)
  .share();
}

コンポーネントでngOnInitメソッドに複数回アクセスすると思いますか?
_console.logngOnInitに入れて確認してください。

その場合、サービスでthis.websocketを新しいものでオーバーライドするためです。

代わりにそのようなものを試してください:

@Injectable()
export class MemberService implements OnInit {

  private websocket: any;
  private websocketSubject$ = new BehaviorSubject<any>();
  private websocket$ = this.websocketSubject$.asObservable();

  private destination = 'wss://notessensei.mybluemix.net/ws/time';

  constructor() { }

  ngOnInit() { }

  listenToTheSocket(): Observable<any> {
    if (this.websocket) {
      return this.websocket$;
    }

    this.websocket = new WebSocket(this.destination);

    this.websocket.onopen = () => console.log(`WebService Connected to ${this.destination}`);

    this.websocket.onmessage = (res) => this.websocketSubject$.next(res => res.data);
  }
}

BehaviorSubjectは、サブスクライブする前にイベントを受信した場合、最後の値を送信します。さらに、それは主題なので、share演算子を使用する必要はありません。

1
maxime1992