I'm trying to understand how to work with angular 4 and websockets. In my older projects with angularjs (1.x) I followed this guide: AngularJs Websocket Service
The solution in this guide is to store a Promise and an Id for each request inside a collection, so when the server sends back a response with this id, I can retrieve the right Promise from the collection and choose to use "notify" if I expect more messages, and "resolve" if is a one shot request-response.
In Angular 4 is preferable to work with RxJs Observable / Subject. A basic use of websocket can be found in this post: Angular (2+) Websockets Tutorial. But how can I achieve an equivalent mechanism from the first post with RxJs?
This is my starting point Service, it is a simple echo client:
import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs/Rx';
import * as Rx from 'rxjs/Rx';
@Injectable()
export class WebsocketService {
private socketUrl: any = 'wss://echo.websocket.org';
private subject: Rx.Subject<MessageEvent>;
private ws : any;
public messages: Subject<any>;
constructor() {
this.messages = <Subject<any>>this.connect()
.map((response: MessageEvent): any => {
let data = JSON.parse(response.data);
return data;
});
}
connect() : Rx.Subject<MessageEvent> {
if (!this.subject) {
this.subject = this.create(this.socketUrl);
console.log("Successfully connected: " + this.socketUrl);
}
return this.subject;
}
private create(url): Rx.Subject<MessageEvent> {
this.ws = new WebSocket(url);
let observable = Rx.Observable.create(
(obs: Rx.Observer<MessageEvent>) => {
this.ws.onmessage = obs.next.bind(obs);
this.ws.onerror = obs.error.bind(obs);
this.ws.onclose = obs.complete.bind(obs);
return this.ws.close.bind(this.ws);
})
let observer = {
next: (data: Object) => {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(data));
}
}
}
return Rx.Subject.create(observer, observable);
}
}