Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Websocket in Angular 4 and RxJS confusion

I am trying to learn RxJS with websockets and Angular 4, and found a good example here. I'm hoping someone can help explain the example as a few things are confusing.

They have created 2 Angular services, the Websocket Service:

import { Injectable } from '@angular/core';
import * as Rx from 'rxjs/Rx';

@Injectable()
export class WebsocketService {
  constructor() { }

  private subject: Rx.Subject<MessageEvent>;

  public connect(url): Rx.Subject<MessageEvent> {
    if (!this.subject) {
      this.subject = this.create(url);
      console.log("Successfully connected: " + url);
    } 
    return this.subject;
  }

  private create(url): Rx.Subject<MessageEvent> {
    let ws = new WebSocket(url);

    let observable = Rx.Observable.create(
    (obs: Rx.Observer<MessageEvent>) => {
        ws.onmessage = obs.next.bind(obs);
        ws.onerror = obs.error.bind(obs);
        ws.onclose = obs.complete.bind(obs);
        return ws.close.bind(ws);
    })
let observer = {
        next: (data: Object) => {
            if (ws.readyState === WebSocket.OPEN) {
                ws.send(JSON.stringify(data));
            }
        }
    }
    return Rx.Subject.create(observer, observable);
  }

}

and the Chat service:

import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs/Rx';
import { WebsocketService } from './websocket.service';

const CHAT_URL = 'ws://echo.websocket.org/';

export interface Message {
    author: string,
    message: string
}

@Injectable()
export class ChatService {
    public messages: Subject<Message>;

    constructor(wsService: WebsocketService) {
        this.messages = <Subject<Message>>wsService
            .connect(CHAT_URL)
            .map((response: MessageEvent): Message => {
                let data = JSON.parse(response.data);
                return {
                    author: data.author,
                    message: data.message
                }
            });
    }
}

I've got a number of questions about this:

  1. Why is it necessary to create 2 services? Can't a Subject be an observer and observable (so it could just relay the messages directly without a second Chat service)? What problem does is solve creating 2 services?
  2. In the Websocket Service, why does the last line of the .create function call return ws.close.bind(ws)? What does that do?
  3. How is a disconnect of the websocket handled? Is there a way to make it reconnect?
  4. How should the services close/dispose of the websocket?
like image 908
TSG Avatar asked Aug 30 '17 19:08

TSG


1 Answers

  1. Reuseability
  2. so you can unsubscribe from observable which in turn closes the connection
  3. in the example you gave it would probably be something like (when you have a instance of chatService)

    let sub = chatService.messages.subscribe(()=>{ 
    // do your stuff 
    });
    
    // some where in your code
    sub.unsubscribe() // this will close the connection
    
  4. already answered in 3

like image 55
Arin Avatar answered Nov 19 '22 09:11

Arin