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

React Material Select: The error is caused by the property 'renderValue' with an expected type, as declared within the 'IntrinsicAttributes & SelectProps' type

Encountering an error with React Material Select, specifically on the Render Value function. How can I resolve this issue while using TypeScript? What should be added to the renderValue line? Error: Type '(selected: Array<number>) => string& ...

How to utilize the async pipe on an observable<Object> and connect it to a local variable in the HTML using Angular

Hey there! So, I have this observable called user$ which has a bunch of properties such as name, title, and address. component{ user$:Observable<User>; constructor(private userService:UserService){ this.user$ = this.userService.someMethodRet ...

Angular 2 - Dependency Injection failing to function

I have created two different implementations for an interface and assigned them as providers for two separate components. However, I am encountering the following error: Error: Can't resolve all parameters for ChildComponent: (?). What could be the i ...

What is the procedure for cancelling a file upload in the FileUpload component of PrimeNG?

1. Issue Overview Looking to terminate file upload in PrimeNG's FileUpload component when certain filename patterns are detected. Using Angular 6.0.7 and PrimeNG 6.0.2. 2. Initial Strategy 2.1. HTML Code <p-fileUpload #fileUploader name="file" ...

A guide to implementing typescript with Next.js getStaticProps

I have Next.js set up with the TypeScript feature enabled Currently, I am attempting to utilize the getStaticProps function following the guidelines outlined here: https://nextjs.org/docs/basic-features/typescript Utilizing the GetStaticProps type export ...

A mistake has been identified: The object could potentially be 'null'. TS2531 for window.document

This is my first time integrating TypeScript into my project. When attempting to access something using window.document.getElementById(), I keep encountering the error: Type error: Object is possibly 'null'. TS2531 I've looked online for ...

Comparison between Destructuring in TypeScript and JavaScript

Starting my journey with TypeScript after a background in JavaScript. In the realm of modern JavaScript, one can easily destructure objects like this: let {n,s} = {n:42, s:'test'}; console.log(n, s); // 42 test Assuming TypeScript follows su ...

Issue TS1259: The module "".../node_modules/@types/bn.js/index"" can only be imported as the default using the 'esModuleInterop' flag

Currently, I am utilizing Hiro Stack.js which I obtained from the following link: https://github.com/hirosystems/stacks.js/tree/master/packages/transaction. For additional information, please refer to . Even when attempting to compile a fully commented out ...

"Firebase function fails to return Typescript class variable, resulting in 'undefined'

Being someone with a background in python/golang, I am now delving into ionic2. There seems to be an issue that I can't quite figure out due to my current level of knowledge in this stack. Perhaps I just need a way to reference the outer scope of this ...

How can a particular route parameter in Vue3 with Typescript be used to retrieve an array of strings?

Encountered a build error: src/views/IndividualProgramView.vue:18:63 - error TS2345: Argument of type 'string | string[]' is not assignable to parameter of type 'string'. Type 'string[]' is not assignable to type 'strin ...

Should the null-forgiving operator be avoided when using `useRef`?

Is the following code snippet considered poor practice? const Component: React.FC<{}> = () => { const ref = React.useRef<HTMLDivElement>(null!); return <div ref={ref} />; } I'm specifically questioning the utilization of ...

When initialized within an object, Angular may identify a field as undefined

Whenever I attempt to access a property of the object named "User," it shows up as undefined. However, upon logging the complete object to the console, the field appears with the necessary data. Here is the console log output: perfil.component.ts:42 unde ...

Discover the latest DOM elements using Webdriverio 5

Currently, I am developing a REact based CMS application that features a form with multiple carousels. I am encountering an issue where the webdriverio implementation is unable to locate an element, even though the same xpath works fine when tested manua ...

When defining a stripe in TypeScript using process.env.STRIPE_SECRET_KEY, an error of "string | undefined" is encountered

Every time I attempt to create a new stripe object, I encounter the error message "Argument of type 'string | undefined' is not assignable to parameter of type 'string'. Type 'undefined' is not assignable to type 'string& ...

When I pass an array of objects to Firefox (using TypeScript) and retrieve the data, I find that I am unable to retrieve it in the form of an array of objects

When it comes to saving and retrieving data from a Firebase database, I seem to be encountering an issue where the type of data retrieved does not match what I am expecting. Let me break down what I am doing and the problem I am facing: Saving data To sa ...

Tips for refreshing the apollo cache

I have been pondering why updating data within the Apollo Client cache seems more challenging compared to similar libraries such as react-query. For instance, when dealing with a query involving pagination (offset and limit) and receiving an array of item ...

Angular: Issue with subscribed variable visibility on screen

I am currently developing user management functionality. When a button is clicked, the goal is to save a new user and display an incoming password stored in the system. Below is a snippet of my code: onClick() { /*Code to populate the newUser variable from ...

What is the best method to extract the values of objects in an array that share

var data= [{tharea: "Rare Disease", value: 3405220}, {tharea: "Rare Disease", value: 1108620}, {tharea: "Rare Disease", value: 9964980}, {tharea: "Rare Disease", value: 3881360}, ...

Is there a way to retrieve the attributes of a generic object using an index in TypeScript?

I'm currently working on a function that loops through all the attributes of an object and converts ISO strings to Dates: function findAndConvertDates<T>(objectWithStringDates: T): T { for (let key in Object.keys(objectWithStringDates)) { ...

Why does TypeScript include a question mark next to the argument when GraphQL specifies it as nullable true?

// image.entity.ts import { Field, ObjectType } from '@nestjs/graphql'; import { Column, DeleteDateColumn, Entity, PrimaryGeneratedColumn, } from 'typeorm'; @ObjectType() @Entity() export class ImageEntity { @PrimaryGenerate ...