I this article, you’ll learn how to create an Angular client using RxJS WebSocketSubject, WebSocket, Node.js and Express.js
Given the wide interest in my previous article on WebSocket, Node and Express (thanks to everyone 😅) I created a simple Angular client that allows you to communicate with the server made in the previous tutorial (PS: I also updated the libraries related to the server component 🎉).
This mini-project (source code here and working DEMO here**🎠 **— try to open two or more browser windows and play with the broadcast button) can be summarized in the following code snippet:
import { Component, ViewChild, ElementRef, OnInit, AfterViewInit } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { WebSocketSubject } from 'rxjs/observable/dom/WebSocketSubject';
export class Message {
constructor(
public sender: string,
public content: string,
public isBroadcast = false,
) { }
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements AfterViewInit {
//...
private socket$: WebSocketSubject<Message>;
constructor() {
this.socket$ = WebSocketSubject.create('ws://localhost:8999');
this.socket$
.subscribe(
(message) => this.serverMessages.push(message) && this.scroll(),
(err) => console.error(err),
() => console.warn('Completed!')
);
}
//...
}
websocket-node-express-component.ts hosted with ❤ by GitHub
As you can see, we are initializing a WebSocketSubject
and specifying the type of object we intend to obtain from the server (in this case, simply a Message
).
Obviously, the definition of the obtained object must conform to what is communicated by the server (for this reason I always suggest working with shared objects inside your repo— in this case we are facilitated by using both server and client side of the same language, Typescript 😎).
Coming back to the definition of the WebSocketSubject
we can say that this is a very useful tool of RxJS library that represents a wrapper around the w3c-compatible WebSocket object provided by the browser.
It is therefore sufficient to subscribe and define the actions that our code must perform:
The rest of the client shows a little graphic trick to make the scroll of the interface a little bit smooth without using any additional library 😏. If you want, checkout the animation algorithm at 60fps with the calculation of the remaining scroll.
You could get the same thing with the CSS only but I preferred to get my hands dirty to refresh the characteristics of the @ViewChild
and ElementRef
).
private getDiff(): number {
const nativeElement = this.viewer.nativeElement;
return nativeElement.scrollHeight - (nativeElement.scrollTop + nativeElement.clientHeight);
}
private scrollToBottom(t = 1, b = 0): void {
if (b < 1) {
b = this.getDiff();
}
if (b > 0 && t <= 120) {
setTimeout(() => {
const diff = this.easeInOutSin(t / 120) * this.getDiff();
this.viewer.nativeElement.scrollTop += diff;
this.scrollToBottom(++t, b);
}, 1 / 60);
}
}
private easeInOutSin(t): number {
return (1 + Math.sin(Math.PI * t - Math.PI / 2)) / 2;
}
websocket-node-express-component-scroll.ts hosted with ❤ by GitHub
The same applies to the calculation of the badge color based on the initials typed by the user ;)
public getSenderInitials(sender: string): string {
return sender && sender.substring(0, 2).toLocaleUpperCase();
}
private getSenderColor(sender: string): string {
const alpha = '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZ';
const initials = this.getSenderInitials(sender);
const value = Math.ceil((alpha.indexOf(initials[0]) + alpha.indexOf(initials[1])) * 255 * 255 * 255 / 70);
return '#' + value.toString(16).padEnd(6, '0');
}
websocket-node-express-component-initials-color.ts hosted with ❤ by GitHub
For demonstration purposes only, within the server I added a 1000ms timeout to make the server response more “real” in case you want to try the compiled code locally.
In just a few steps, we’ve created an Angular client using RxJS WebSocketSubject: soon we can go deep in catching errors and reconnection policies, but this will come in another story 🎉
#angular #node-js #express #web-development