Using WebSockets in Angular 4

Currently in the process of developing a chat application using Angular 4 and WebSocket. I found guidance from this Angular WebSocket tutorial

This is the source code for the WebsocketService:

import { Injectable } from '@angular/core';
import * as Rx from 'rxjs/Rx';

@Injectable()
export class WebsocketService {
  constructor() { }

  private subject: Rx.Subject<MessageEvent>;

  public connect(url): Rx.Subject<MessageEvent> {
    if (!this.subject) {
      this.subject = this.create(url);
      console.log("Successfully connected: " + url);
    } 
    return this.subject;
  }

  private create(url): Rx.Subject<MessageEvent> {
    let ws = new WebSocket(url);

    let observable = Rx.Observable.create(
    (obs: Rx.Observer<MessageEvent>) => {
        ws.onmessage = obs.next.bind(obs);
        ws.onerror = obs.error.bind(obs);
        ws.onclose = obs.complete.bind(obs);
        return ws.close.bind(ws);
    })
let observer = {
        next: (data: Object) => {
            if (ws.readyState === WebSocket.OPEN) {
                ws.send(JSON.stringify(data));
            }
        }
    }
    return Rx.Subject.create(observer, observable);
  }

}

This is the ChatService:

import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs/Rx';
import { WebsocketService } from './websocket.service';

const CHAT_URL = 'ws://echo.websocket.org/';

export interface Message {
    author: string,
    message: string
}

@Injectable()
export class ChatService {
    public messages: Subject<Message>;

    constructor(wsService: WebsocketService) {
        this.messages = <Subject<Message>>wsService
            .connect(CHAT_URL)
            .map((response: MessageEvent): Message => {
                let data = JSON.parse(response.data);
                return {
                    author: data.author,
                    message: data.message
                }
            });
    }
}

The application functions well, but I aim to monitor the connection status. It's important to know if there are interruptions or server downtime.

To address this, I attempted to implement an isServerOn() function within the WebsocketService class like so:

isServerOn(): Observable<boolean> {
    return Observable.of(!!this.subject);
}

Unfortunately, this did not resolve the issue. Has anyone else encountered a similar problem before?

Appreciate any insights shared in advance.

Answer №1

To optimize your Angular application, consider integrating type definitions for socket.io-client. Create a service with the following structure:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Observer } from 'rxjs/Observer';
import { Message } from '../model/message';
import { Event } from '../model/event';

import * as socketIo from 'socket.io-client';

const SERVER_URL = 'https://yourserverhost.com';

@Injectable()
export class SocketService {
    private socket;

    public initSocket(): void {
        this.socket = socketIo(SERVER_URL);
    }

    public send(message: Message): void {
        this.socket.emit('message', message);
    }

    public onEvent(event: Event): Observable<any> {
        return new Observable<Event>(observer => {
            this.socket.on(event, () => observer.next());
        });
    }
}

Create an enum for Events:

export enum Event {
    CONNECT = 'connect',
    DISCONNECT = 'disconnect'
}

Subscribe to the service methods in your Angular component like so:

export class ChatComponent implements OnInit {
  constructor(private socketService: SocketService) { }

   ngOnInit(): void {
    this.initIoConnection();
  }

  private initIoConnection(): void {
    this.socketService.initSocket();

    this.ioConnection = this.socketService.onMessage()
      .subscribe((message: Message) => {
        this.messages.push(message);
      });


    this.socketService.onEvent(Event.CONNECT)
      .subscribe(() => {
        console.log('Connected to the server');
      });

    this.socketService.onEvent(Event.DISCONNECT)
      .subscribe(() => {
        console.log('Disconnected');
      });
  }
}

For a complete chat project utilizing Node.js, WebSockets, and Angular, check out this repository: https://github.com/luixaviles/socket-io-typescript-chat

Answer №2

I'm not entirely clear on your intentions with

 return Observable.of(!!this.subject);

It may not function as expected. A better approach would be to create your own BehaviorSubject and then return the corresponding Observable like this:

isServerActive(): Observable<boolean> {
    return this.serverStatusSubject.asObservable();
}

Then, at the appropriate points in your online/offline code, you can update the value using:

this.serverStatusSubject.next(true/false);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Why is my Angular 2 service not showing up in my application?

Trying to access a JSON file using an Angular service has been unsuccessful. While I can easily read and bind the JSON data without the service, attempting to do so with the service results in an error message: Failed to load resource: the server responde ...

Tips for configuring the node_modules/lib path in an AngularJS project

I have been trying to see if the image is working properly. Is there a way to utilize global libraries for node_module? The installation seems to be in the correct place - c:\user\AppData\Roaming\npm\node_modules However, I a ...

What is the best way to display a custom row overlay in ag-grid?

I am looking to display a customized message when no users are found using ag-grid in Angular6. Below is the code snippet: ngOnInit() { this.gridOptions.frameworkComponents.loadingCellRenderer = TableLoadingComponent; this.rowBuffer = 0; this.rowSel ...

Tips for sending class objects with Typescript/React

I need to establish an Array of items with different characteristics as a Prop on my component. My goal is to transmit an array of items with unique properties to a component. Here's an example of what my array of objects might look like: ` let dish ...

Enhance your production bundle in Angular CLI 7 by incorporating defer/async attributes

Recently, I have been experiencing some performance issues with a new site built using Angular CLI 7, particularly when accessed through mobile browsers. Upon further investigation, I pinpointed the main cause of the poor performance to be the absence of p ...

The type 'string' cannot be assigned to type 'ImageSourcePropType'

Context Attempting to utilize a SVG component in React Native with the xlinkHref property within an Image tag. The SVG file was converted into a React Native Component (TSX) using the tool provided at . While simple SVG icons have been successfully used be ...

What are the steps for importing a file into a React app that is built using Create React App as plain text?

Objectives I aim to showcase code snippets from the project itself for reference. I intend to keep the displayed code up-to-date with its implementation. I prefer not to remove myself from create-react-app This React project, built using create-react-ap ...

Utilizing Angular to Fetch JSON Data from a Server

I am currently retrieving data from a JSON file that resides on a server and is updated regularly. It's crucial for me to access this JSON content in order to consistently showcase the most recent information on my website. At present, I have stored ...

The combination of using the .share() method with the .subscribe() method is resulting in

I encountered an issue while attempting to utilize share() with subscribe(). Despite starting with subscribe, I received the following error message. How can this be resolved? The main goal is to execute the logic within subscribe. Share is necessary to p ...

Angular Owl Carousel doesn't slide horizontally, it slides vertically

Within my Angular project, I incorporated an Owl Carousel into the home-component.html file. Here is a snippet of the code: <section> <div class="container"> <h1 class="products-title">New Arrivals</h1> ...

Issues arising from the implementation of a multi-item carousel using Flickity in Angular

I am currently attempting to implement a multi-item carousel/content slider in Angular, but I am encountering an issue with the Flickity carousel. The items within the carousel are aligning vertically instead of horizontally, which is not the desired behav ...

Angular2 Event:keyup triggers the input to lose focus

I am working on a component with an input element that is bound to a property. I want the input field to update in real time as I type in it. Here is my current code: <input type="text" #updatetext [value]="item.name" (keyup)="updateItem(item.$key, up ...

Guide to Angular Interface Styling - Ambiguous Suggestions

After reviewing the Angular style guide for interfaces, I find two recommendations particularly perplexing: The suggestion to use a class instead of an interface for services and declarables (components, directives, and pipes) leaves me puzzled. Similarl ...

Using the p-multiSelect component in Primeng for Angular 2

Within the user.component.html template, I am utilizing a Primeng component. <p-multiSelect name="roles_id" [(ngModel)]="selectedRoles" [options]="user.roles"></p-multiSelect> When loading the input data, how can ...

The Fusion of Apollo GraphQL Server and TypeScript: A Match Made

Lately, I've been immersed in a project that utilizes the node.js + express + typescript + Apollo server stack. During my research on Apollo client, I came across the TypeScript section, but surprisingly found little information regarding TypeScript f ...

What steps should I take to resolve the eslint issue indicating that a TypeScript props interface is not being utilized, even though it is being used?

One of my components utilizes AvatarProps for its props: Below is the interface declaration for AvatarProps: export interface AvatarProps { userName: string; userLastName: string; userImg?: string; onPress?: Function; backgroundColorAvatar?: str ...

What are the steps to resolve the "EADDRINUSE: address already in use :::3000" error in an integration test?

While testing my simple endpoint using jest and superTest in my TypeScript project, I encountered the listen EADDRINUSE: address already in use :::3000 error. The file app.ts is responsible for handling express functionalities and it is the one being impo ...

Should I opt for 'typeof BN' or the BN Constructor when working with TypeScript and "bn.js"?

Note: Despite the recommendation to use BigInts instead of bn.js, I am currently working with a legacy codebase that has not been migrated yet. Below is the code that compiles and executes without any issues: import { BN } from "bn.js"; import a ...

Issue: When attempting to read the length of a property in Angular 6, a TypeError is being thrown because the property is

Unable to retrieve values from an array using the TS code below: this.dataservice.get("common/public/getAllCategories", null).subscribe(data => { //console.log('categories'+JSON.stringify( data)); this.categoriesarray = data; }); var ...

Creating dynamic CSS in Angular 2 and beyond

When working with a JavaScript variable containing style information, I encountered different approaches in AngularJS and Angular2+: menuBgColor = "red"; In AngularJS, I could use dynamically embedded styles like this: <div> <style> ...