Angular2/Websocket: how to return an observable for incoming websocket messages

13,448

I put it on a plunker and I added a function for sending message to the Websocket endpoint. Here is the important edit:

public GetInstanceStatus(): Observable<any>{
    this.websocket = new WebSocket("ws://echo.websocket.org/"); //dummy echo websocket service
    this.websocket.onopen =  (evt) => {
        this.websocket.send("Hello World");
    };
    return Observable.create(observer=>{
        this.websocket.onmessage = (evt) => { 
            observer.next(evt);
        };
    })
    .share();
}

Update
As you mentioned in your comment, a better alternative way is to use Observable.fromEvent()

websocket = new WebSocket("ws://echo.websocket.org/");
public GetInstanceStatus(): Observable<Event>{
    return Observable.fromEvent(this.websocket,'message');
}

plunker example for Observable.fromEvent();

Also, you can do it using WebSocketSubject, although, it doesn't look like it's ready yet (as of rc.4):

constructor(){
  this.websocket = WebSocketSubject.create("ws://echo.websocket.org/");
}

public sendMessage(text:string){
  let msg = {msg:text};
  this.websocket.next(JSON.stringify(msg));
} 

plunker example

Share:
13,448

Related videos on Youtube

Bing Lu
Author by

Bing Lu

Updated on July 13, 2022

Comments

  • Bing Lu
    Bing Lu almost 2 years

    I'm going to use Angular2 to receive websocket incoming messages and update a webpage based on those received messages. Right now, I'm using a dummy echo websocket service and will replace it.

    From my understanding, the function which receive websocket messages has to return an observable that is subscribed by a handler who will update the webpage. But I can't figure out how to return an observable.

    Code snippet is attached below. The MonitorService creates a websocket connection and return an observable containing the received messages.

    @Injectable()
    export class MonitorService {
    
        private actionUrl: string;
        private headers: Headers;
        private websocket: any;
        private receivedMsg: any;
        constructor(private http: Http, private configuration: AppConfiguration) {
    
            this.actionUrl = configuration.BaseUrl + 'monitor/';
            this.headers = new Headers();
            this.headers.append('Content-Type', 'application/json');
            this.headers.append('Accept', 'application/json');
        }
    
        public GetInstanceStatus = (): Observable<Response> => {
            this.websocket = new WebSocket("ws://echo.websocket.org/"); //dummy echo websocket service
            this.websocket.onopen =  (evt) => {
                this.websocket.send("Hello World");
            };
    
            this.websocket.onmessage = (evt) => { 
                this.receivedMsg = evt;
            };
    
            return new Observable(this.receivedMsg).share();
        }
    
    }
    

    Below is another component which subscribes to the observable returned from above and updates webpages correspondingly.

    export class InstanceListComponent {
      private instanceStatus: boolean
      private instanceName: string
      private instanceIcon: string
      constructor(private monitor: MonitorService) { 
        this.monitor.GetInstanceStatus().subscribe((result) => {
            this.setInstanceProperties(result);
        });
      }
    
      setInstanceProperties(res:any) {
        this.instanceName = res.Instance.toUpperCase();
        this.instanceStatus = res.Status;
        if (res.Status == true)
        {
          this.instanceIcon = "images/icon/healthy.svg#Layer_1";
        } else {
          this.instanceIcon = "images/icon/cancel.svg#cancel";
        }
      }
    }
    

    Now, I'm running into this error in the browser console TypeError: this._subscribe is not a function