J'ai une application basée sur ngrx/store (v2.2.2) et rxjs (v5.1.0) qui écoute un socket Web pour les données entrantes à l'aide d'un observable. Lorsque je lance l'application, je reçois parfaitement les données entrantes.
Cependant, après un certain temps (les mises à jour arrivent assez rarement), la connexion semble se perdre et je ne reçois plus de données entrantes. Mon code:
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));
}
})
}
}
Que dois-je faire pour reconnecter le socket Web à l'expiration du délai, afin que l'observable continue d'émettre des valeurs entrantes?
J'ai jeté un coup d'œil à quelques questions et réponses ici , ici et ici et il n'a pas semblé répondre à cette question (d'une manière que je puisse comprendre).
Remarque: la Websocket située à wss://notessensei.mybluemix.net/ws/time
est sous tension et émet un horodatage une fois par minute (au cas où on voudrait le tester).
Les conseils sont grandement appréciés!
En fait, il y a maintenant un WebsocketSubject dans rxjs!
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' }));
Il gère la reconnexion lorsque vous vous réabonnez à une connexion interrompue. Donc, par exemple, écrivez ceci pour vous reconnecter:
subject.retry().subscribe(...)
Voir la documentation pour plus d'informations. Malheureusement, la boîte de recherche ne montre pas la méthode, mais vous la trouvez ici:
http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#static-method-webSocket
cette navigation ne fonctionne pas dans mon navigateur. Recherchez "webSocket" sur cette page.
Source: http://reactivex.io/rxjs/file/es6/observable/dom/WebSocketSubject.js.html#lineNumber15
Pour rxjs 6, implémentation websocket.
import { webSocket } from 'rxjs/websocket';
let subject = webSocket('ws://localhost:8081');
Ce n'est peut-être pas la bonne réponse, mais c'est beaucoup trop pour un commentaire.
Le problème pourrait venir de votre service:
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();
}
Pensez-vous que votre composant utilise plusieurs fois la méthode ngOnInit
?
Vous devriez essayer de mettre un console.log
dans ngOnInit
pour en être sûr.
Parce que si vous le faites, dans votre service, vous remplacez le this.websocket
par un nouveau.
Vous devriez essayer quelque chose comme ça à la place:
@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 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);
}
}
La BehaviorSubject
enverra la dernière valeur si elle reçoit un événement avant de vous y abonner. De plus, comme il s'agit d'un sujet, inutile d'utiliser l'opérateur share
.