abstruse
Version:
Abstruse CI
111 lines (95 loc) • 2.65 kB
text/typescript
import { ConfigService } from '../services/config.service';
import { Observable, Subscriber, Observer } from 'rxjs';
export enum ConnectionStates {
CONNECTING,
CONNECTED,
CLOSED,
RETRYING
}
export class RxWebSocket {
config: ConfigService;
socket: WebSocket;
messageQueue: string[] = [];
didOpen: (e: Event) => void;
willOpen: () => void;
didClose: (e?: any) => void;
_out: Observable<any>;
_in: Observer<any>;
constructor() {
this.config = new ConfigService();
}
selector(e: MessageEvent) {
return JSON.parse(e.data);
}
get out(): Observable<any> {
if (!this._out) {
this._out = Observable.create((subscriber: Subscriber<any>) => {
this.socket = new WebSocket(this.config.wsurl);
if (this.willOpen) {
this.willOpen();
}
this.socket.onopen = (e: any) => {
this.flushMessages();
if (this.didOpen) {
this.didOpen(e);
}
};
this.socket.onclose = (e: any) => {
if (e.wasClean) {
subscriber.complete();
if (this.didClose) {
this.didClose(e);
}
} else {
subscriber.error(e);
}
};
this.socket.onerror = (e: any) => subscriber.error(e);
this.socket.onmessage = (e: any) => subscriber.next(this.selector(e));
return () => {
this.socket.close();
this.socket = null;
this._out = null;
};
});
}
return this._out;
}
send(message: any) {
let data = typeof message === 'string' ? message : JSON.stringify(message);
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
this.socket.send(data);
} else {
this.messageQueue.push(data);
}
}
get in(): Observer<any> {
if (!this._in) {
this._in = {
next: (message: any) => {
let data = typeof message === 'string' ? message : JSON.stringify(message);
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
this.socket.send(message);
} else {
this.messageQueue.push(message);
}
},
error: (err: any) => {
this.socket.close(3000, err);
this.socket = null;
},
complete: () => {
this.socket.close();
this.socket = null;
}
};
}
return this._in;
}
flushMessages() {
let messageQueue = this.messageQueue;
while (messageQueue.length > 0 && this.socket.readyState === WebSocket.OPEN) {
this.socket.send(messageQueue.shift());
}
}
}