Angular使用RxJS,它本質上是一個反應式擴展的javascript實現。這是一個使用可觀察序列組成異步和基於事件的程序的庫,很是適合使用WebSockets。javascript
簡而言之,RxJS容許咱們從websocket鏈接中偵聽新消息,而後在「X」事件發生時執行操做。這方面的一個例子能夠是實時聊天應用程序。假設咱們有3我的鏈接到咱們的聊天應用程序,其中一我的發送消息。若是咱們想在收到消息時在應用程序中執行某些操做,那麼咱們能夠簡單地訂閱「新消息」事件並在觸發事件時處理該事件。css
在咱們的角度應用程序中實現WebSockets的最佳方法是將咱們的WebSockets和事件封裝在服務中,而後在咱們但願與websocket交互的任何組件中調用該服務。html
使用Angular CLI,經過在命令行中鍵入如下內容來建立新應用程序:前端
ng new websocket_tutorial
這應該建立一個新的,功能齊全的Angular應用程序,咱們將在其中實現基於websocket的服務。爲了確保它的工做類型:java
ng serve
您應該但願看到服務器在端口4200上成功啓動。若是您在首選的Web瀏覽器中導航到localhost:4200,您應該會看到'app works!' 在瀏覽器中顯示。如今咱們已經啓動並運行了咱們的基本應用程序,讓咱們繼續建立咱們的websocket服務。web
爲了讓咱們開始,咱們將建立一個很是簡單的服務,該服務將鏈接到任何給定的URL並返回咱們能夠在其餘服務/組件中訂閱的RxJS主題,以便偵聽來自鏈接套接字的任何傳入消息。瀏覽器
ng g service websocket
咱們須要重新服務頂部的rxjs庫中導入*。這將使咱們可以創造既能觀察又能觀察的主體。這實際上意味着咱們的主題將觀察咱們的websocket以獲取任何傳入消息,並將這些消息廣播到剛好訂閱此服務的任何組件。bash
1 import { Injectable } from '@angular/core'; 2 import {Subject, Observer, Observable} from 'rxjs';; 3 4 @Injectable() 5 export class WebsocketService { 6 constructor() { } 7 8 private subject: Rx.Subject<MessageEvent>; 9 10 public connect(url): Rx.Subject<MessageEvent> { 11 if (!this.subject) { 12 this.subject = this.create(url); 13 console.log("Successfully connected: " + url); 14 } 15 return this.subject; 16 } 17 18 private create(url): Rx.Subject<MessageEvent> { 19 let ws = new WebSocket(url); 20 21 let observable = Rx.Observable.create( 22 (obs: Rx.Observer<MessageEvent>) => { 23 ws.onmessage = obs.next.bind(obs); 24 ws.onerror = obs.error.bind(obs); 25 ws.onclose = obs.complete.bind(obs); 26 return ws.close.bind(ws); 27 }) 28 let observer = { 29 next: (data: Object) => { 30 if (ws.readyState === WebSocket.OPEN) { 31 ws.send(JSON.stringify(data)); 32 } 33 } 34 } 35 return Rx.Subject.create(observer, observable); 36 } 37 38 }
接下來咱們要作的是建立一個與咱們的websockets接口的第二個服務,它將做爲一種適配器,它將咱們的websocket的輸出調整爲咱們能夠在前端輕鬆使用的形式。再次使用angular-cli建立此服務:服務器
ng g service chat
這應該在根目錄中建立一個chat.service.ts。在這個文件中,咱們想要作這樣的事情:websocket
1 import { Injectable } from '@angular/core'; 2 import { Observable, Subject } from 'rxjs'; 3 import { WebsocketService } from './websocket.service'; 4 5 const CHAT_URL = 'ws://echo.websocket.org/'; 6 7 export interface Message { 8 author: string, 9 message: string 10 } 11 12 @Injectable() 13 export class ChatService { 14 public messages: Subject<Message>; 15 16 constructor(wsService: WebsocketService) { 17 this.messages = <Subject<Message>>wsService 18 .connect(CHAT_URL) 19 .pipe(map((response: MessageEvent): Message => { 20 let data = JSON.parse(response.data); 21 return { 22 author: data.author, 23 message: data.message 24 } 25 })); 26 } 27 }
若是是6.0以上的rxjs版本,map函數能夠直接使用,代碼以下:
1 this.messages = <Subject<Message>>wsService 2 .connect(CHAT_URL) 3 .map((response: MessageEvent): Message => { 4 let data = JSON.parse(response.data); 5 return { 6 author: data.author, 7 message: data.message 8 } 9 });
最後,咱們要更新咱們的app.component.ts文件,以便它導入咱們新建立的聊天服務,並容許咱們將消息推送到此websocket:
1 import { Component } from '@angular/core'; 2 import { WebsocketService } from './websocket.service'; 3 import { ChatService } from './chat.service'; 4 5 @Component({ 6 selector: 'app-root', 7 templateUrl: './app.component.html', 8 styleUrls: ['./app.component.css'], 9 providers: [ WebsocketService, ChatService ] 10 }) 11 export class AppComponent { 12 13 constructor(private chatService: ChatService) { 14 chatService.messages.subscribe(msg => { 15 console.log("Response from websocket: " + msg); 16 }); 17 } 18 19 private message = { 20 author: 'tutorialedge', 21 message: 'this is a test message' 22 } 23 24 sendMsg() { 25 console.log('new message from client to websocket: ', this.message); 26 this.chatService.messages.next(this.message); 27 this.message.message = ''; 28 } 29 30 }
最後,咱們須要更新咱們的app組件的html頁面,以便咱們能夠實際使用咱們在組件文件中定義的sendMsg()函數:
<!-- app.component.html -->
1 <h1> 2 Angular6 WebSocket 教程 3 </h1> 4 5 <button (click)="sendMsg()">發送消息</button>
完成這些更改後,經過轉到根目錄並輸入如下命令來提供應用程序:
ng serve
您應該在瀏覽器中看到 "Angula6 WebSocket 教程" 和 「發送消息」 按鈕。
打開控制檯並單擊按鈕幾回,您應該看到您的應用程序向測試websocket服務器發送和接收消息。