2016-05-04 41 views
6

Inizio a creare un'applicazione. Ci sono molti componenti Ognuno di loro ha bisogno di una parte di dati da 1 webSocket. L'esempio di un oggetto da receiveing ​​websocket:Il modo migliore per condividere dati WebSocket tra più componenti in Angular 2?

enter image description here

Ogni angolare 2 componente necessita 1 campo da receiveing ​​oggetto. È possibile creare 1 servizio, che si connetterà a webSocket, ricevere dati e condividerlo tra tutti i componenti? Penso che sarà una buona soluzione.

ora sto usando il metodo seguente:

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); 
 
    }; 
 
}

ricevo i dati in un componente principale e voglio condividere tra i componenti che utilizzano le istanze del componente. Ma penso che sia una cattiva idea e esiste una soluzione migliore.

+0

Si potrebbe aggiungere il servizio al vostro ' bootstrap() 'comando in cui si impostano i provider. Quindi, i componenti ottengono il servizio tramite l'integrazione delle dipendenze dal costruttore. Ora puoi utilizzare il servizio in ogni componente che lo ha iniettato. – rinukkusu

risposta

5

Certo che si può condividere il vostro servizio per impostare il suo provider quando bootstrap l'applicazione:

bootstrap(AppComponent, [ WebSocketService ]); 

In questo modo condividerai la stessa istanza del tuo servizio nell'intera applicazione. Voglio dire quando si inietta il servizio WebSocketService, l'istanza corrispondente sarà la stessa indipendentemente dal componente/servizio.

Per essere in grado di condividere i dati ricevuti, vorrei sfruttare un osservabile caldo. Per impostazione predefinita, gli osservabili sono freddi, quindi è necessario utilizzare l'operatore share.

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(); 
} 

componenti che vorrebbero ricevere i dati dal socket web potrebbe utilizzare questo osservabile in questo modo:

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

consulta questo articolo per maggiori dettagli nella sezione "approccio event-based":

+0

Quando provo a testare questa soluzione ci sono alcuni problemi. Il mio IDE aggiunge automaticamente l'importazione di un Observable: [link] (http://data3.floomby.com/files/share/4_5_2016/14/fWyVy8kOfUioABCs795DXw.jpg). Un'app cade con un errore: [collegamento] (http://data3.floomby.com/files/share/4_5_2016/14/DTCuEmJmxUKrP4HUhmQQ.jpg). La mia struttura di progetto: [collegamento] (http://data3.floomby.com/files/share/4_5_2016/14/wVoBYKAcTUGxKEZ7Rb765A.jpg). Puoi aiutarmi con questo errore. – Edward

+1

Dovresti importare la classe Observable in questo modo: 'importa {Observable} da 'rxjs/Observable';' oppure 'importa {Observable} da 'rxjs/Rx';' –

0

Qualcosa di simile a quanto segue (a seconda delle esigenze concrete):

@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, ...] 
});