{"id":2151,"date":"2022-09-05T21:53:16","date_gmt":"2022-09-05T19:53:16","guid":{"rendered":"https:\/\/nguenkam.com\/blog\/?p=2151"},"modified":"2022-09-05T21:53:16","modified_gmt":"2022-09-05T19:53:16","slug":"how-to-use-websockets-with-rxjs-and-angular","status":"publish","type":"post","link":"https:\/\/nguenkam.com\/blog\/index.php\/2022\/09\/05\/how-to-use-websockets-with-rxjs-and-angular\/","title":{"rendered":"How to use WebSockets with RxJS and Angular?"},"content":{"rendered":"\n<p>WebSocket is a web communication protocol that allows two-way communication between a client and a server.<\/p>\n\n\n\n<p>What makes that technology appealing is that unlike regular TCP sockets, WebSockets use the same port as the HTTP protocol, which is port 80.<\/p>\n\n\n\n<p>This means that when using WebSockets you don\u2019t have to worry about firewalls blocking that port and preventing your data to flow between client and server.<\/p>\n\n\n\n<p><a rel=\"noreferrer noopener\" href=\"https:\/\/caniuse.com\/#feat=websockets\" target=\"_blank\">T<\/a>he technology has been around for a while, long enough to enjoy excellent support across all browsers according to\u00a0<a rel=\"noreferrer noopener\" href=\"https:\/\/caniuse.com\/#search=websocket\" target=\"_blank\">caniuse.com<\/a>:<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" src=\"https:\/\/nguenkam.com\/blog\/wp-content\/uploads\/2022\/09\/image-7-1024x347.png\" alt=\"\" class=\"wp-image-2165\" width=\"689\" height=\"233\" srcset=\"https:\/\/nguenkam.com\/blog\/wp-content\/uploads\/2022\/09\/image-7-1024x347.png 1024w, https:\/\/nguenkam.com\/blog\/wp-content\/uploads\/2022\/09\/image-7-300x102.png 300w, https:\/\/nguenkam.com\/blog\/wp-content\/uploads\/2022\/09\/image-7-768x260.png 768w, https:\/\/nguenkam.com\/blog\/wp-content\/uploads\/2022\/09\/image-7-1536x521.png 1536w, https:\/\/nguenkam.com\/blog\/wp-content\/uploads\/2022\/09\/image-7.png 1725w\" sizes=\"(max-width: 689px) 100vw, 689px\" \/><\/figure><\/div>\n\n\n\n<p>PS:  but, keep in mind that &#8230;\u00a0some older browsers may not support WebSockets.\u00a0<\/p>\n\n\n\n<h4>WebSockets in Angular<\/h4>\n\n\n\n<p>Angular utilizes RxJS which is essentially a javascript implementation of reactive extensions. This is a library for composing asynchronous and event-based programs using observable sequences and is perfect for working with WebSockets.<\/p>\n\n\n\n<p>This is actually almost too easy. You just have to import the\u00a0<strong>webSocket<\/strong>\u00a0function from RxJs, call it with the URL of your WebSocket, and\u2026 done!<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import {webSocket, WebSocketSubject} from 'rxjs\/webSocket';\r\nmyWebSocket: WebSocketSubject = webSocket('ws:\/\/localhost:8000');<\/code><\/pre>\n\n\n\n<p>You now have an RxJs subject that you can subscribe to in order to receive some data:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>myWebSocket.asObservable().subscribe(dataFromServer => \/\/...);<\/code><\/pre>\n\n\n\n<p>And if you want to send data to the server, simply use the next method of your subject:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>myWebSocket.next({message: 'some message'});<\/code><\/pre>\n\n\n\n<p>Also note that when you subscribe to a WebSocket subject, you can register callbacks to be notified when an error happens or when the connection is closed, just like with a regular observable:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>myWebSocket.subscribe(    \r\n   msg => console.log('message received: ' + msg), \r\n   \/\/ Called whenever there is a message from the server    \r\n   err => console.log(err), \r\n   \/\/ Called if WebSocket API signals some kind of error    \r\n   () => console.log('complete') \r\n   \/\/ Called when connection is closed (for whatever reason)  \r\n);<\/code><\/pre>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h4>Example<\/h4>\n\n\n\n<p>An example of this could be in a real-time chat application. Say we have 3 people connected to our chat application and one of them sends a message. If we want to do something in our application whenever we receive a message then we can simply subscribe to a \u2018new-message\u2019 event and handle the event whenever it is triggered.<\/p>\n\n\n\n<p><strong>PS: <\/strong><em>The best way to implement WebSockets in our angular applications would be to encapsulate our WebSockets and events in a service and then call that service in whatever components we wish to interact with a websocket.<\/em><\/p>\n\n\n\n<ul><li><span class=\"has-inline-color has-luminous-vivid-orange-color\">Creating our Websocket Service<\/span><\/li><\/ul>\n\n\n\n<p>To get us started we\u2019ll be creating a very simple service that will connect to any given URL and return an RxJS subject that we can subscribe to in other services\/components in order to listen for any incoming messages from the connected socket.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ng g service websocket<\/code><\/pre>\n\n\n\n<p>We\u2019ll need to import * from the rxjs library at the top of our new service. This will allow us to create the subject that will both observe and be observable. This essentially means our subject will watch our websocket for any incoming messages and will broadcast these messages to any components that happen to be subscribing to this service.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { Injectable } from \"@angular\/core\";\r\nimport * as Rx from \"rxjs\/Rx\";\r\n\r\n@Injectable()\r\nexport class WebsocketService {\r\n  constructor() {}\r\n\r\n  private subject: Rx.Subject&lt;MessageEvent>;\r\n\r\n  public connect(url): Rx.Subject&lt;MessageEvent> {\r\n    if (!this.subject) {\r\n      this.subject = this.create(url);\r\n      console.log(\"Successfully connected: \" + url);\r\n    }\r\n    return this.subject;\r\n  }\r\n\r\n  private create(url): Rx.Subject&lt;MessageEvent> {\r\n    let ws = new WebSocket(url);\r\n\r\n    let observable = Rx.Observable.create((obs: Rx.Observer&lt;MessageEvent>) => {\r\n      ws.onmessage = obs.next.bind(obs);\r\n      ws.onerror = obs.error.bind(obs);\r\n      ws.onclose = obs.complete.bind(obs);\r\n      return ws.close.bind(ws);\r\n    });\r\n    let observer = {\r\n      next: (data: Object) => {\r\n        if (ws.readyState === WebSocket.OPEN) {\r\n          ws.send(JSON.stringify(data));\r\n        }\r\n      }\r\n    };\r\n    return Rx.Subject.create(observer, observable);\r\n  }\r\n}<\/code><\/pre>\n\n\n\n<p>Next what we want to do is to create a second service that will interface with our websockets and will act as a type of adapter which will adapt the output from our websocket into a form that we can easily work with in the frontend. Again create this service using the angular-cli:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ng g service chat<\/code><\/pre>\n\n\n\n<p>This should create a chat.service.ts within your root directory. In this file we are going to do something like so:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { Injectable } from \"@angular\/core\";\r\nimport { Observable, Subject } from \"rxjs\/Rx\";\r\nimport { WebsocketService } from \".\/websocket.service\";\r\n\r\nconst CHAT_URL = \"ws:\/\/echo.websocket.org\/\";\r\n\r\nexport interface Message {\r\n  author: string;\r\n  message: string;\r\n}\r\n\r\n@Injectable()\r\nexport class ChatService {\r\n  public messages: Subject&lt;Message>;\r\n\r\n  constructor(wsService: WebsocketService) {\r\n    this.messages = &lt;Subject&lt;Message>>wsService.connect(CHAT_URL).map(\r\n      (response: MessageEvent): Message => {\r\n        let data = JSON.parse(response.data);\r\n        return {\r\n          author: data.author,\r\n          message: data.message\r\n        };\r\n      }\r\n    );\r\n  }\r\n}<\/code><\/pre>\n\n\n\n<ul><li><span class=\"has-inline-color has-luminous-vivid-orange-color\">Updating our App Component<\/span><\/li><\/ul>\n\n\n\n<p>Finally we\u2019ll want to update our app.component.ts file so that it imports our newly created chat service and allows us to push messages to this websocket:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { Component } from \"@angular\/core\";\r\nimport { WebsocketService } from \".\/websocket.service\";\r\nimport { ChatService } from \".\/chat.service\";\r\n\r\n@Component({\r\n  selector: \"app-root\",\r\n  templateUrl: \".\/app.component.html\",\r\n  styleUrls: &#91;\".\/app.component.css\"],\r\n  providers: &#91;WebsocketService, ChatService]\r\n})\r\nexport class AppComponent {\r\n  constructor(private chatService: ChatService) {\r\n    chatService.messages.subscribe(msg => {\r\n      console.log(\"Response from websocket: \" + msg);\r\n    });\r\n  }\r\n\r\n  private message = {\r\n    author: \"tutorialedge\",\r\n    message: \"this is a test message\"\r\n  };\r\n\r\n  sendMsg() {\r\n    console.log(\"new message from client to websocket: \", this.message);\r\n    this.chatService.messages.next(this.message);\r\n    this.message.message = \"\";\r\n  }\r\n}<\/code><\/pre>\n\n\n\n<p>Finally we\u2019ll need to update our html page for our app component so that we can actually use the sendMsg() function that we defined in our component file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;!-- app.component.html -->\r\n&lt;h1>\r\n  Angular 2 WebSockets Tutorial\r\n&lt;\/h1>\r\n\r\n&lt;button (click)=\"sendMsg()\">Send Message&lt;\/button><\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>WebSocket is a web communication protocol that allows two-way communication between a client and a server. What makes that technology appealing is that unlike regular TCP sockets, WebSockets use the same port as the HTTP protocol, which is port 80. This means that when using WebSockets you don\u2019t have to worry about firewalls blocking that [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":2152,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[37],"tags":[382,161,217,593],"_links":{"self":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/2151"}],"collection":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=2151"}],"version-history":[{"count":2,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/2151\/revisions"}],"predecessor-version":[{"id":2166,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/2151\/revisions\/2166"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/media\/2152"}],"wp:attachment":[{"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=2151"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=2151"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nguenkam.com\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=2151"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}