Websocket in Angular 4 and RxJS confusion

2020-05-19 02:54发布

问题:

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?

回答1:

  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