Exploring the power of RxJs through chaining observers

In my Angular application, I am utilizing Observables to set up a WebSocket service. Currently, I have the following implementation:

readwrite(commands: command[]) : Observable<response[]>{
    const observable = new Observable((observer)=>{
        this.socket.subscribe((socket:WebSocket)=>{
            const id = this.uid++;
            //// Unsure About This Part ////
            this.observerMap[id]={
                next: next=>{
                    observer.next(next);
                    delete this.observerMap[id]; ////<---- Intended Action
                },
                error: error=> observer.error(error),
                complete: ()=>observer.complete()
            }
            socket.send(JSON.stringify({requestType:'ReadWrite', commands: commands, id: id}));
        });
    });
    return observable;
}

In the ws.onmessgae event handler, I handle incoming messages like so:

{
    const result = JSON.parse(event.data);
    this.observerMap[result.id]?.next(result.commands);
}

While this approach gets the job done, I am exploring cleaner ways to manage these operations. The cleanup of the observableMap[] cannot be handled within ws.onmessage due to the existence of observers across multiple messages. Additionally, the cleanup should occur only after the completion of .next() execution in the Observer, leading me to the current solution. Using .pipe() triggers execution before the observer completes its operation.

Are there more efficient methods to chain these operations together seamlessly?

Answer №1

It is recommended to make use of the complete function in this manner:

readwrite(commands: command[]) : Observable<response[]>{
    const observabe = new Observable((observer)=>{
        this.socket.subscribe((socket:WebSocket)=>{
            const id = this.uid++;
            this.observerMap[id]={
                next: next=>{
                    observer.next(next);
                },
                error: error=> observer.error(error),
                complete: ()=> { 
                   observer.complete()
                   delete this.observerMap[id];
                }
            }
            socket.send(JSON.stringify({requestType:'ReadWrite', commands: commands, id: id}));
        });
    });
    return observable;
}

then in onmessage:

{
    const result = JSON.parse(event.data);
    this.observerMap[result.id]?.next(result.commands);
    this.observerMap[result.id]?.complete();
}

Answer №2

The Subject is a powerful tool that fits perfectly in this scenario. Your implementation of the observerMap essentially embodies the functionality of a Subject, which makes it incredibly user-friendly.

  1. To begin, declare your Subject within a service:
export class MessageService {

    message$ = new Subject<any>;
    constructor() { }
  }
  1. Whenever you need to handle incoming messages with onmessage, simply execute a .next() every time a new message is received:
  {
        const result = JSON.parse(event.data);
        this.messageService.message$.next(result.commands);
  }
  1. In your component, just subscribe to the Subject:
{
    this.messageService.message$.subsrcibe(console.log)
}

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

Can you conduct testing on Jest tests?

I am in the process of developing a tool that will evaluate various exercises, one of which involves unit-testing. In order to assess the quality of tests created by students, I need to ensure that they are effective. For example, if a student provides the ...

What is the best way to make an attribute in an interface mandatory only when another attribute is set to true

How can a relative be made required only when another attribute is true? For Example: interface ITesteProps { required: boolean content{!required && '?'}: string } I understand that this code is not valid. Is it possible to make the ...

Warning from React 17: Unexpected presence of <a> tag inside <div> tag in server-rendered HTML

I've checked out the existing solutions and still can't seem to make it work. components/NavBar.tsx import { Box, Link } from "@chakra-ui/react"; import { FunctionComponent } from "react"; import NextLink from "next/link ...

Issue regarding angularjs type definitions

I am facing an issue with installing typings for Angular and I need some guidance on how to resolve the error. Any suggestions or assistance would be greatly appreciated! Below is the error message that I encountered: ERROR in C:\Users\test&b ...

Error: Virtual script not located; possibly absent <script lang="ts" / "allowJs": true / within the jsconfig.json.volar

https://i.sstatic.net/dFaVQ.png I noticed an error in my footer component in VueJs (TypeScript template) as depicted by the image showing blue squiggly lines. ...

Having trouble locating node_modules post deployment?

Although the title may lead you astray, please stay with me for a moment. I've created a basic Angular2 application in Visual Studio 2015 and have now deployed it to Azure. While having node_modules in the development environment worked perfectly fi ...

The 'required' validator in Mongoose seems to be malfunctioning

I've been attempting to validate the request body against a Mongoose model that has 'required' validators, but I haven't been successful in achieving the desired outcome so far. My setup involves using Next.js API routes connected to Mo ...

Issue: Prior to initiating a Saga, it is imperative to attach the Saga middleware to the Store using applyMiddleware function

I created a basic counter app and attempted to enhance it by adding a saga middleware to log actions. Although the structure of the app is simple, I believe it has a nice organizational layout. However, upon adding the middleware, an error occurred: redu ...

Enhancing User Authentication: Vue 3 with TypeScript Login

Recently, I came across a new technology called Supabase and noticed that most resources mention registration on JavaScript instead of TypeScript. As I started working on a project using Vue 3 + TypeScript, I encountered some errors that I need help resolv ...

Arranging Angular Array-like Objects

I am in possession of an item: { "200737212": { "style": { "make": { "id": 200001510, "name": "Jeep", "niceName": "jeep" }, "model": { "id": "Jeep_Cherokee", "name": "Cherokee", "nice ...

Using TypeScript with Vue allows you to customize the default export of Vue

Currently experimenting with Vue and TypeScript, attempting to compile to AMD in my tsconfig file. The type definition in vue/types/index.d.ts for Vue.js includes: export default Vue; However, this results in TypeScript compiling it like this: import V ...

Retrieve the essential information needed from the REST API

I have a test wordpress blog set up. To enhance the functionality, I developed an angular app that utilizes the wordpress rest api. The app makes a call to an endpoint to retrieve categories. However, the JSON response contains unnecessary data for my appl ...

Single array returned by observable

Issue: I am looking for a way to consolidate the multiple arrays returned individually into a single array. Solution: fetchAllRiders() { var distanceObs = Observable.create(observer => { this.http.get(this.API + '/driver/all').map(res = ...

Exploring the capabilities of indexing an array within an array in Nativescript

I am working with JSON data retrieved from an API and trying to figure out how to index an array inside an array using Nativescript. JS: cart [{ JS: "_id": "5d3988cd287bad2943686920", JS: "userid": "11E76234942299FCC13FFA163EDC2079", JS: "products": ...

What should be the output when ending the process using process.exit(1)?

I need to update my code by replacing throw new Error('Unknown command.') with a log statement and process.exit(1);. Here is the example code snippet: private getCommandByName = (name: string): ICommand => { try { // try to fetch ...

Module is absent in JavaScript but present in TypeScript

As I delve into coding a vscode extension by following a tutorial, I encountered an issue with importing in my server.ts file. The directory structure looks like this: ...

Issue with incorrect inference of TextField `helperText` when using Formik with Material-UI

Upgrading to react-scripts 5 has caused an issue with the helperText on the TextField component. My TypeScript knowledge is not strong, so I'm having trouble fixing it. Here's more information about the problem: The error message: TS2322: Type & ...

Exploring the capabilities of the hardware camera in Angular 2

Struggling to implement the tutorial in Angular2. The challenge lies in making navigator.mediaDevices.getUserMedia function properly. The error message indicates that mediaDevices is not recognized on type 'navigator'. Refer to the media capture ...

Error encountered while attempting to generate migration in TypeORM entity

In my project, I have a simple entity named Picture.ts which contains the following: const { Entity, PrimaryGeneratedColumn, Column } = require("typeorm"); @Entity() export class Picture { @PrimaryGeneratedColumn() ...

The 'data' property is absent in the 'never[]' type, whereas it is necessary in the type of product data

Hello, I am new to TypeScript and I'm struggling with fixing this error message: Property 'data' is missing in type 'never[]' but required in type '{ data: { products: []; }; }'. Here is my code snippet: let medias :[] ...