UNPKG

webstomp-obs

Version:

Stomp over websocket using observable

140 lines (110 loc) 5.9 kB
import { Observer } from 'rxjs/Observer'; import { Observable } from 'rxjs/Observable'; import { Subject } from 'rxjs/Subject'; import { ConnectableObservable } from 'rxjs/Observable/ConnectableObservable'; import 'rxjs/add/operator/multicast'; import 'rxjs/add/operator/finally'; import { IConnectedObservable } from './types'; import Frame from './frame'; import { ACK, AckHeaders, SendHeaders } from './headers'; interface ISubscriptions { [key: string]: Observer<Frame>; } interface IObservables { [key: string]: Observable<Frame>; } // STOMP Connected Client Class // export class ConnectedClient { private connection: IConnectedObservable private broadcastSubscribers: IObservables private broadcastReceipterObservable: Observable<Frame> private broadcastReceipterObserver: Observer<Frame> private broadcastErrorObservable: Observable<Frame> private broadcastErrorObserver: Observer<Frame> private broadcastConnectionErrorObservable: Observable<Frame> private broadcastConnectionErrorObserver: Observer<Frame> constructor(connection: IConnectedObservable) { this.connection = connection; // subscription callbacks indexed by subscriber's ID this.broadcastSubscribers = {}; } public send = (destination: string, body: string = '', headers: SendHeaders = {destination}): void => { const headerToSend = { ...headers, destination}; this.connection.messageSender.next(this.connection.protocol.send(headerToSend, body)); } public begin = (transaction?: string) => { this.connection.messageSender.next(this.connection.protocol.begin(transaction)); } public commit = (transaction: string) => { this.connection.messageSender.next(this.connection.protocol.commit(transaction)); } public abort = (transaction: string) => { this.connection.messageSender.next(this.connection.protocol.abort(transaction)); } public ack = (messageID: string, subscription: string, headers?: AckHeaders) => { this.connection.messageSender.next(this.connection.protocol.ack(messageID, subscription, headers)); } // [NACK Frame](http://stomp.github.com/stomp-specification-1.1.html#NACK) public nack = (messageID: string, subscription: string, headers?: AckHeaders) => { if (this.connection.protocol.nack) { this.connection.messageSender.next(this.connection.protocol.nack(messageID, subscription, headers)); } else { throw 'Nack unsupported operation'; } } // [RECEIPT Frame](http://stomp.github.com/stomp-specification-1.1.html#RECEIPT) public receipt = (): Observable<Frame> => { // create one and only one broadcast receiver if (!this.broadcastReceipterObservable) { const connectedSubscribe: ConnectableObservable<Frame> = this.connection.messageReceipted .finally(() => this.broadcastReceipterObserver ? this.broadcastReceipterObserver = null : null) .multicast(() => new Subject()) connectedSubscribe.connect(); this.broadcastReceipterObservable = connectedSubscribe.refCount(); } return this.broadcastReceipterObservable; } // Return an Observable containing the event when a connection error occure public connectionError = (): Observable<Frame> => { // create one and only one broadcast receiver if (!this.broadcastConnectionErrorObservable) { const connectionErrorSubscribe: ConnectableObservable<Frame> = this.connection.errorReceived .finally(() => this.broadcastConnectionErrorObserver ? this.broadcastConnectionErrorObserver = null : null) .multicast(() => new Subject()) connectionErrorSubscribe.connect(); this.broadcastConnectionErrorObservable = connectionErrorSubscribe.refCount(); } return this.broadcastConnectionErrorObservable; } // Return an Observable containing the error when an error occure public error = (): Observable<Frame> => { // create one and only one broadcast receiver if (!this.broadcastErrorObservable) { const connectedSubscribe: ConnectableObservable<Frame> = this.connection.errorReceived .finally(() => this.broadcastErrorObserver ? this.broadcastErrorObserver = null : null) .multicast(() => new Subject()) connectedSubscribe.connect(); this.broadcastErrorObservable = connectedSubscribe.refCount(); } return this.broadcastErrorObservable; } // subscribe to a destination // return an Observable which you can unsubscribe public subscribe = (destination: string, headers: {id?: string, ack?: ACK} = {}): Observable<Frame> => { return this.connection.subscribeTo(destination, headers); } // subscribe to a destination only once for multiple subscribers // return an Observable which you can unsubscribe public subscribeBroadcast = (destination: string, headers: {id?: string, ack?: ACK} = {}): Observable<Frame> => { // create one and only one dedicated observable per destination if (!this.broadcastSubscribers[destination]) { const connectedSubscribe: ConnectableObservable<Frame> = this.subscribe(destination, headers) .finally(() => this.broadcastSubscribers[destination] ? delete this.broadcastSubscribers[destination] : null) .multicast(() => new Subject()) connectedSubscribe.connect(); this.broadcastSubscribers[destination] = connectedSubscribe.refCount(); } return this.broadcastSubscribers[destination]; } }