Angular WebSockets with PieSocket

bob.ts - Aug 30 '21 - - Dev Community

I've wanted to work with WebSockets for a while and struggled to find a good project to implement them on. Then, just about the time that I did find 'that' project, I ran into PieSocket.

They are self-described as "WebSockets as a Service."

Here, I was able to implement communications between browsers on separate machines with ease.

Code

Here, I'd like to share my SocketService ...

import { Injectable } from "@angular/core";
import { Observable } from "rxjs";

export interface SocketMessage {
  type: string;
  payload: any;
};

@Injectable()
export class SocketService {

  websocket: any;

  constructor() {
    this.connectWebSocket();
  }

  connectWebSocket = (): void => {
    const CLUSTER_ID: string = 'FROM-PIE-SOCKET--CLUSTER-ID';
    const CHANNEL_ID: string = 'FROM-PIE-SOCKET--CHANNEL-ID';
    const API_KEY: string = 'FROM-PIE-SOCKET--API-KEY';

    try {
      this.websocket = new WebSocket(`wss://${ CLUSTER_ID }.piesocket.com/v3/${ CHANNEL_ID }?api_key=${ API_KEY }`);

      this.websocket.onopen = () => {
        const initMessage: SocketMessage = {
          type: 'initial',
          payload: ''
        };
        this.publish(initMessage);
      };
    } catch (error) {
      console.log(error);
    }
  };

  messagesOfType = (type: string): Observable<SocketMessage> => {
    return new Observable(observer => {
      this.websocket.onmessage = (eventString: MessageEvent) => {
        const event: SocketMessage = JSON.parse(eventString.data);
        if (event.type === type) {
          observer.next(event);
        }
      };
    });
  };

  errorHandler = (): Observable<Event> => {
    return new Observable(observer => {
      this.websocket.onerror = (event: Event) => {
        observer.next(event);
      };
    });
  };

  publish = (message: SocketMessage) => {
    try {
      this.websocket.send(JSON.stringify(message));
    } catch (error) {
      console.log(error);
    }
  };

}

Enter fullscreen mode Exit fullscreen mode

Since I was just testing things, I've got the cluster id, channel, and api key stored within the code. If this were a project for a client, I would have secured these details.

If you read my article Angular Communication Between Tabs, you would realize that the "initialize" (in this case connectWebSocket) is pulled out to make testing easier. Additionally, I have added a try-catch block to allow for error handling.

The function messagesOfTypes returns an observable that watches the websocket.onmessages and returns data, when needed.

There's an errorHandler function that is used by the initialization try-catch.

The publish function does just what it says.

Implementation

Here's the code to publish ...

this.socketService.publish({ type: 'student', payload: 'bob fornal'});
Enter fullscreen mode Exit fullscreen mode

And, here's the code to use messagesOfType ...

this.broadcast.messagesOfType('student').subscribe((message: SocketMessage) => {
  const student: string = message.payload;
  this.publishStudents();
});
Enter fullscreen mode Exit fullscreen mode

Summary

Having wanted to work with WebSockets for a while, I found one. Additionally, I ran into PieSocket who made the learning process easy.

This code shows how I was able to implement communications between browsers on separate machines with ease.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .