2017-08-23 2 views
2

Ich versuche zu verstehen, wie man mit eckigen 4 und websockets arbeitet. In meinen älteren Projekten mit AngularJS (1.x), gefolgt ich diese Anleitung: AngularJs Websocket ServiceAngular 4 RxJs WebSocket

Die Lösung in diesem Handbuch ein Versprechen und eine ID für jede Anforderung innerhalb einer Sammlung zu speichern, so dass, wenn der Server sendet eine Antwort Mit dieser ID kann ich das richtige Versprechen aus der Sammlung abrufen und wählen, "Benachrichtigen" zu verwenden, wenn ich mehr Nachrichten erwarte, und "Auflösen", wenn es sich um eine einmalige Anfrage-Antwort handelt.

In Angular 4 ist es vorzuziehen, mit RxJs Observable/Subject zu arbeiten. Eine grundlegende Verwendung von Websocket kann in diesem Beitrag gefunden werden: Angular (2+) Websockets Tutorial. Aber wie kann ich einen gleichwertigen Mechanismus aus dem ersten Post mit RxJs erreichen?

Das ist mein Ausgangspunkt Service, ist es ein einfaches Echo-Client:

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

@Injectable() 
export class WebsocketService { 

    private socketUrl: any = 'wss://echo.websocket.org'; 
    private subject: Rx.Subject<MessageEvent>;  
    private ws : any; 
    public messages: Subject<any>; 

    constructor() { 
     this.messages = <Subject<any>>this.connect() 
      .map((response: MessageEvent): any => { 
       let data = JSON.parse(response.data); 
       return data; 
      }); 
    } 

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

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

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

} 
+0

Bitte Quellcode Beispiel für das, was Sie versucht haben. – cgTag

+1

Ich habe meinen Startpunktcode hinzugefügt. – retrobitguy

Antwort

3

Der erste Beitrag ist über eine Buchse Single-Anfrage-Single-Wirkungs-Anrufe. Ich würde dem Autor wirklich empfehlen, nur HTTP zu verwenden. Ihre Anforderung notify ist eine bessere Anwendung für WebSockets.

Ich würde vorschlagen, Sie Multicast (share()) die beobachtbare und wer benötigt Daten aus dem WebSocket abonnieren. Hier ist ein Beispiel mit eckigen Komponenten.

@Injectable() 
export class ChatService { 
    public messages: Subject<Message>; 
    public shared: Observable<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 
       } 
      }); 
     this.shared = this.messages.share(); //multicast 
    } 
} 

Und dann Komponenten und austragen.

export class SomeComponent { 

    private componentId:number = this.getUniqueId(); 
    private subscription; 

    constructor(private chatService: ChatService) { } 

    ngOnInit(){ 
     this.subscription = this.chatService.shared.subscribe(msg => { //subscribe to multicast obs. 
      console.log("Response from websocket: " + msg); 
      if (msg.comp_id == this.componentId) { //comp_id returned by server 
       //message I am interested in 
      } 
     }); 
    } 
    ngOnDestroy(){ 
     this.subscription.unsubscribe(); 
    } 

    private message = { 
     componentId: this.componentId, 
     messageId:this.getUniqueId(), 
     author: 'tutorialedge', 
     message: 'this is a test message' 
    } 

    sendMsg(message:string) { 
     this.chatService.messages.next({ 
      componentId: this.componentId, 
      messageId: this.getUniqueId(), 
      author: 'tutorialedge',//? 
      message: message 
     }); 
    } 

} 

Weitere WebSocket RxJs info hier ist ein great video von der Legende selbst und das source code