2016-05-04 6 views
6

Ich fange an, eine Anwendung zu erstellen. Es gibt viele Komponenten. Jeder von ihnen benötigt einen Teil der Daten von 1 WebSocket. Das Beispiel eines Objekts durch receiveing ​​WebSocket:Der beste Weg, WebSocket-Daten zwischen mehreren Komponenten in Angular 2 zu teilen?

enter image description here

jeder Winkel 2-Komponenten benötigen 1 Feld aus Objekt receiveing. Ist es möglich, 1 Service zu machen, der sich mit webSocket verbindet, Daten empfängt und diese zwischen allen Komponenten teilt? Ich denke, es wird eine gute Lösung sein.

Jetzt bin ich mit dem nächsten Ansatz:

getConfigCallback() { 
 
    this.connectionSockets.telemetry = io(this.config.connections.telemetry); 
 
    this.connectionSockets.controlFlow = new WebSocket(this.config.connections.controlFlow.server + ':' + this.config.connections.controlFlow.port); 
 

 
    this.connectionSockets.telemetry.on('telemetry', function(data) { 
 
     console.log(data); 
 
    }); 
 

 
    this.connectionSockets.controlFlow.onopen = function(data) { 
 
     console.log('onOpen', data); 
 
    }; 
 

 
    this.connectionSockets.controlFlow.onmessage = function(data) { 
 
     console.log('onMessage', data); 
 
    }; 
 
}

Ich empfange Daten in einer Hauptkomponente und will, dass es zwischen den Komponenten Instanzen der Verwendung der Komponente teilen. Aber ich denke, es ist eine schlechte Idee und es gibt eine bessere Lösung.

+0

Sie könnten den Dienst Ihres hinzufügen ' bootstrap() 'Befehl, wo Sie Ihre Provider einrichten. Dann erhalten Sie in Ihren Komponenten den Service über die Abhängigkeitsinjektion vom Konstruktor. Jetzt können Sie den Dienst in jeder Komponente verwenden, die Sie injizieren. – rinukkusu

Antwort

5

Sicher, dass Sie Ihren Service gesetzt sein Anbieter teilen kann, wenn die Anwendung Bootstrapping:

bootstrap(AppComponent, [ WebSocketService ]); 

Auf diese Weise teilen Sie dieselbe Instanz Ihres Dienstes in der gesamten Anwendung. Ich meine, wenn Sie den Dienst WebSocketService injizieren, wird die entsprechende Instanz unabhängig von der Komponente/dem Dienst identisch sein.

Um die empfangenen Daten teilen zu können, würde ich eine heiße Observable nutzen. Standardmäßig sind Observables kalt, daher müssen Sie den Operator share verwenden.

initializeWebSocket(url) { 
    this.wsObservable = Observable.create((observer) => { 
    this.ws = new WebSocket(url); 

    this.ws.onopen = (e) => { 
     (...) 
    }; 

    this.ws.onclose = (e) => { 
     if (e.wasClean) { 
     observer.complete(); 
     } else { 
     observer.error(e); 
     } 
    }; 

    this.ws.onerror = (e) => { 
     observer.error(e); 
    } 

    this.ws.onmessage = (e) => { 
     observer.next(JSON.parse(e.data)); 
    } 

    return() => { 
     this.ws.close(); 
    }; 
    }).share(); 
} 

Komponenten, die von der Web-Socket-Daten erhalten möchten diese beobachtbaren auf diese Weise nutzen könnten:

@Component({ 
    (...) 
}) 
export class SomeComponent { 
    constructor(private service:WebSocketService) { 
    this.service.wsObservable.subscribe((data) => { 
     // use data 
    }); 
    } 
} 

in diesem Artikel für weitere Details in der „ereignisbasierten Ansatz“ Abschnitt:

+0

Wenn ich versuche, diese Lösung zu testen, gibt es einige Probleme. Meine IDE fügt automatisch den Import eines Observable hinzu: [link] (http://data3.floomby.com/files/share/4_5_2016/14/fWyVy8kOfUioABCs795DXw.jpg). Eine App hat einen Fehler: [link] (http://data3.floomby.com/files/share/4_5_2016/14/DTCuEmJmxUKrP4HUhmQQ.jpg). Meine Projektstruktur: [link] (http://data3.floomby.com/files/share/4_5_2016/14/wVoBYKAcTUGxKEZ7Rb765A.jpg). Kannst du mir bei diesem Fehler helfen? – Edward

+1

Sie sollten die Observable-Klasse folgendermaßen importieren: "{Observable} von 'rxjs/Observable' importieren; 'oder' {Observable} von' rxjs/Rx 'importieren; ' –

0

So etwas wie die folgenden (je nach konkreten Anforderungen):

@Injectable() 
class WsService { 
    comp1Data = new BehaviorSubject(); 
    comp2Data = new BehaviorSubject(); 

    constructor() { 
    getData().subscribe(val => { 
     ... 
     this.compXData.next(someValue); 
    }); 
    } 
    ... 
} 
@Component({...}) 
export class Component1 { 
    constructor(wsService:WsService) { 
    wsService.comp1Data.subscribe(value => this.data = value); 
    } 
} 
@NgModule({ 
    directives: [AppComponent, Component1], 
    bootstrap: [AppComponent], 
    providers: [WsService, ...] 
});