オブザーバブルを使用して着信データの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を見ました here 、 here and here そしてこの質問に対処するようには見えませんでした)。
注:wss://notessensei.mybluemix.net/ws/time
のwebsocketはライブで、1分に1回タイムスタンプを発行します(テストする場合)。
アドバイスは大歓迎です!
実際、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
Rxjs 6の場合、websocket実装。
import { webSocket } from 'rxjs/websocket';
let subject = webSocket('ws://localhost:8081');
これは良い答えではないかもしれませんが、コメントするには多すぎます。
問題はあなたのサービスから来るかもしれません:
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.log
をngOnInit
に入れて確認してください。
その場合、サービスで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
演算子を使用する必要はありません。