Transferring the methods of Angular websocket into a dedicated service

I need assistance with a component that performs two tasks...

  1. Establishes a connection to the server via websocket
  2. Sends a message and displays the response.

The current implementation is functional, and here is the code snippet for the component:

app.component.ts

import { Component } from '@angular/core';
import { WebSocketSubject } from 'rxjs/observable/dom/WebSocketSubject';

export class Message {
  constructor(
      public sender: string,
      public content: string,
      public isBroadcast = false,
  ) { }
}

@Component({
  selector: 'app-terminal',
  templateUrl: './terminal.component.html',
  styleUrls: ['./terminal.component.scss']
})
export class TerminalComponent {

  public serverMessages = new Array<Message>();
  public clientMessage = '';
  public isBroadcast = false;
  public sender = 'client';

  private socket$: WebSocketSubject<Message>;

  server1 = 'ws://localhost:8999';

  constructor() {}

  public send() {
      const message = new Message(this.sender, this.clientMessage, this.isBroadcast);
      this.serverMessages.push(message);
      this.socket$.next(message);
      this.clientMessage = '';
  }

  connectToServer(serverUrl) {

      this.serverMessages = [];
      this.clientMessage = '';

      this.socket$ = new WebSocketSubject(serverUrl);

      this.socket$.subscribe(
          (message) => this.serverMessages.push(message),
          (err) => console.error(err),
          () => console.warn('Completed!')
      );

  }

}

While both methods - connectToServer() and send() - are operational, I seek to consolidate them into a service for reusability across various components without duplication of code.

Hence, I've introduced the service:

This is my progress so far:

import { Injectable } from '@angular/core';
import { WebSocketSubject } from 'rxjs/observable/dom/WebSocketSubject';

export class Message {
  constructor(
      public sender: string,
      public content: string,
      public isBroadcast = false,
  ) { }
}

@Injectable({
  providedIn: 'root'
})
export class WebsocketService {

  public serverMessages = new Array<Message>();
  public clientMessage = '';
  public isBroadcast = false;
  public sender = 'client';

  private socket$: WebSocketSubject<Message>;

  server1 = 'ws://localhost:8999';

  constructor() {}

  connect(serverUrl) {

   // Implementation pending

  }

  send(message) {

    // Implementation pending

  }

}

My query pertains to incorporating these methods in the service so they can be easily invoked from the component.

Answer №1

Components in Angular receive services through dependency injection.

If you already have an injectable service, the next step is to add it to a module in the providers section. This is typically done in app.module.ts:

...
providers: [
 ...
 WebsocketService,
 ...
],
...

Once added, you can inject the service into components by including it in the constructor like this:

@Component({
  selector: 'app-terminal',
  templateUrl: './terminal.component.html',
  styleUrls: ['./terminal.component.scss']
})
export class TerminalComponent {

  constructor(private websocketService: WebsocketService) {}

}

In the above example, I used the private modifier for the constructor parameter websocketService. This allows access to websocketService as a private variable throughout the TerminalComponent class, enabling function calls like:

this.websocketService.connect(serverUrl)
this.websocketService.send(message)

One possible issue with this setup is that the WebsocketService is provided by the root injector, making it a singleton shared across all components. Consequently, invoking the connect function from one component and then from another would overwrite the instance of this.socket$ variable in the service.

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

Creating a custom Map type in TypeScript

I am exploring the concept of defining a Map type in Typescript using generics. Essentially, I want to create something similar to: EntityMap<U, V>, where U can only be either a string or a number This is what I have managed to come up with so far: ...

Creating an asynchronous reducer using ngrx: A step-by-step guide

Exploring the realm of Angular, I am delving into the creation of an asynchronous reducer to handle API calls within my application. The ultimate aim is to fetch files from an API whenever the loadFiles action is activated. In order to achieve this, I dev ...

The JSX component cannot be 'FieldArray' at this time

I'm working on a next.js project and using the Formik component. However, I encountered a type error that says "'FieldArray' cannot be used as a JSX component." Can anyone help me resolve this issue? Here is the error message: 'FieldAr ...

What is the best way to switch to a different screen in a React Native application?

I've recently dived into the world of React Native and embarked on a new project. The initial screen that greets users upon launching the app is the "welcome screen," complete with a prominent 'continue' button. Ideally, clicking this button ...

Add a custom filter to the active route for a stylish look

I am trying to dynamically change the color of elements in my navbar by creating a filter in my typescript code. I have a string with values like 'greyscale(73%) saturate(1400%)'. How can I apply this string to the fa-icon's filter property ...

"Is it possible to add an entire object to formData in one

I am looking to send both an image list and product data to an ASP.net api using formData. I have successfully sent the images, but now I am struggling with appending the entire object. I have come across some methods in JS like JSON.stringfy(object) or Ob ...

Utilizing winston to generate multiple log files with set maximum sizes and daily rotation

Currently, I am utilizing winston for logging with a maximum size and daily rotation. I am interested in having this functionality with one file per API endpoint to define multiple log files. Is there a way to achieve this? Displayed below is my winston ...

What is the best way to extract data from a binary boost::beast::websocket::stream<tcp::socket> and store it in a buffer (such as boost::beast::flat_buffer) without any escaping?

I have implemented boost::beast to retrieve data from a websocket into a std::string. Following the example websocket_sync_client.cpp in boost 1.71.0 closely, with a modification - transmitting input/output in binary form instead of text. Therefore, I incl ...

Having trouble uploading a file with Angular and Spring

The issue of uploading files to BE is causing me some trouble. I have been struggling to get it right, even with the code below: Angular service public saveFile(file: File): Observable<any> { const formData = new FormData(); formDat ...

The main module's postinstall process is initiated before the sub-module's postinstall process

Update: I am seeking guidance on how to install a module from GitHub instead of npm. That's the main query. In case you're wondering why: I'm currently working on some confidential projects and prefer not to publish the code. As a result, ...

The ngFor directive is malfunctioning when attempting to iterate over an array

Take a look at my code below: import { Component } from '@angular/core'; import { ProjectService } from '../../services/project'; import { Project } from '../../models/project'; @Component({ selector: 'projects-comp ...

Creating a reusable API call function with the fetch method

I need to create a general function that can handle all of my API calls from anywhere in my application Currently, I am using React version 16.8.6 and fetch for making API requests Here is what I have come up with so far: Helper.js export function ApiH ...

To successfully transfer a file (whether it be an excel or csv file) into a nodejs environment and then have it update in a mongodb database, follow

Can anyone guide me on how to upload a file, ensuring only Excel or CSV formats are accepted? I then need to read the file using Node.js and update it in a MongoDB database table. Technologies used: Angular 5 for front end, Node.js and MongoDB for backend ...

Strategies for effectively mocking an Angular service: During Karma Jasmine testing, ensure that the spy on service.getShipPhotos is expected to be called once. In the test, it should

Currently, I am working on testing a function called getSingleShip in Angular 12 using Karma-Jasmine 4. The aim is to verify if this function is being called by another function named retrieveShip. However, the test results indicate that getSingleShip has ...

The type of undefined cannot be assigned to the specified type

I am currently working on implementing a pie chart (donut series) in Angular. Below are my HTML, CSS, and TypeScript files. I am following this tutorial resource: Link to CodeSandBox - https://codesandbox.io/s/apx-donut-simple-8fnji?from-embed import ...

typescript: tips for selecting a data type within an object

I need help extracting the type of the 'name' property from an object belonging to the Action interface. interface Action { type: string, payload: { name: string } } I attempted to use Pick<Action, "payload.name">, but it didn&apos ...

Exploring the World of Angular2's RC.1 Dependency Injection

Currently, I am delving into Angular2, but the challenge lies in the fact that every time I come across a helpful tutorial, it does not align with the latest version of Angular2. Despite this, my current struggle involves attempting to inject a service fr ...

Angular 2 RouteConfig and the Importance of Case Sensitivity

Suppose I have a route configuration as follows: @RouteConfig([ { path: '/login', name: 'Login', component: LoginPageContainer } ]) In Angular 2, it is achievable to subscribe to the router like this: this.router.subscribe((nextV ...

Angular material table

I'm having an issue with deleting a record from a table that I created using Angular Material- Even after successfully deleting a record, the view does not refresh. Here is the HTML code snippet - <ng-container matColumnDef="delete"> ...

Divide the string into several segments according to its position value

Here is a piece of text that I would like to divide into multiple sections, determined by the offset and length. If you have any questions or comments and would like to get in touch with ABC, please go to our customer support page. Below is a function ...