What is the best practice for invoking another method within a .subscribe() in Typescript?

I've implemented this method in a certain way, but I'm feeling a bit uneasy about it as I'm not entirely sure if it's considered acceptable practice or just a workaround. Can someone please advise me on whether this is a hack or a valid approach?

The reason behind my implementation is to ensure that the first method finishes executing before the second one starts.

If this is indeed bad practice (which I suspect), I would greatly appreciate suggestions on how to improve this code.

Essentially, I have one method that invokes an HTTP GET request and then, upon subscription, calls another method which in turn interacts with another service using the retrieved data.

 private bind(): void {

        this.Service.get(this.Id)
        .catch(this.logger.log)
        .subscribe(
        (customers: PersonalInfo[]) => { 

        this.customers = customers;               
                this.bindContactInfo();           
        }
        );
    }

private bindContactInfo():void{       

        this.Service.getContactInfo(this.Id)
        .catch(this.logger.log)
        .subscribe(   

        (contactInfo: ContactInformation[]) => {

         // operations here
        }
        );
        }  

Answer №1

Typically, this approach is suitable for a Service, but when considering best practices in coding from a component perspective, there are alternative methods to explore:

Option 1

Avoid manual subscriptions and utilize .do() instead for operations of this nature. Break up your streams into smaller components to facilitate easier testing. Consider structuring your code as follows:

private getPersonalInfo(): Observable<PersonalInfo[]> {
    return this.Service.get(this.Id)
        .catch(this.logger.log)
        .do((customers: PersonalInfo[]) => this.customers = customers);
}

private getContactInfo(): Observable<ContactInformation[]> {
    return this.Service.getContactInfo(this.Id)
        .catch(this.logger.log)
        .do((contactInfo: ContactInformation[]) => this.contactInfo = contactInfo);
}

private getData(): void {
    this.getPersonalInfo()
        .switchMap(() => this.getContactInfo())
        .subscribe();
}

Option 2

If used within a component, consider avoiding statements like this.contactInfo = contactInfo and opt for using | async in the template. Example implementation below:

id$: ReplaySubject<string> = new ReplaySubject<string>(1);

personalInfo$: Observable<PersonalInfo[]> = this.id$
        .switchMap(id => this.Service.get(id))
        .catch(this.logger.log)
        .publishReplay(1)
        .refCount();

contactInfo$: Observable<ContactInformation[]> = this.id$
        .switchMap(id => this.Service.get(id))
        .getContactInfo(this.Id)
        .catch(this.logger.log)
        .publishReplay(1)
        .refCount();

Incorporate the above observables in your template with the following syntax:

<div *ngFor="let personalInfo of personalInfo$ | async">
    ...
</div>

Option 3

Consider adopting a store-concept like ngrx, though this may necessitate significant refactorings.

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

The function navigator.canShare() encountered a permissions denial while running in Typescript

Currently, I am in the process of developing an Angular8 PWA and have successfully implemented webshare to share text content. To my excitement, Chrome has now extended its support for file sharing starting from May 2019. However, while attempting to int ...

Using Angular CLI to proxy websockets with a proxy configuration file, proxy.conf.json

I have been attempting to proxy websockets using ng serve --proxy-config proxy.conf.json in Angular CLI, but I have been unable to get it working. I keep encountering this error message: WebSocket connection to 'ws://stream/connect' failed: Erro ...

Guide on navigating to a specific page with ngx-bootstrap pagination

Is there a way to navigate to a specific page using ngx-bootstrap pagination by entering the page number into an input field? Check out this code snippet: ***Template:*** <div class="row"> <div class="col-xs-12 col-12"> ...

Disable the selection of the year option in the Angular Material Date picker

I need help with disabling the year selection in the Angular Material date picker component. To achieve this, I have implemented a custom native date adapter which only allows the selection of the day and month, keeping the year fixed. Here is a snippet ...

Exploring Blob functionality in TypeScript?

I defined a global Blob object: declare global { interface Blob { prototype: Blob; new (name: string, url: string): Blob; } } It is functioning correctly in this code snippet: export const blobToFile = (blob: Blob) => { let file: File | n ...

Embedding content within various ng-template elements

I'm currently working on developing a button component (app-button) that can utilize multiple templates based on the parent component using it. <div class="ds-u-margin-left--1 ds-u-float--left"> <ng-container *ngTemplateOutlet="icon">< ...

Retrieve an instance of the property class within a property decorator

I'm attempting to create a decorator called @Prop that will assist me in adjusting attributes for custom elements. This is the desired code: class MyCustomClass extends HtmlElement { get content() { return this.getAttribute('content&apo ...

Incorporate a personalized add-button into the material-table interface

My current setup includes a basic material-table structured like this: <MaterialTable options={myOptions} title="MyTitle" columns={state.columns} data={state.data} tableRef={tableRef} // Not functioning properly editabl ...

Error: Issue determining the type of variable. Unable to eliminate type 'any'

I am trying to load some widgets from a template object (possibly JSON in the future). Here's an example: type RectangleTemplate = { name: 'Rectangle'; props: { width: number; height: number; } }; type ButtonTemplate = { nam ...

What is the best way to make Angular Material Fields fill 100% of the container width?

Can you help me figure out how to adjust form fields to maximum width on a screen size less than 840px? I'm currently using Angular, Angular Materials and Flex-Layout. I'm having trouble with making this CSS code work properly. Can you explain ...

Preventing Multiple Login Attempts in Angular.js Using Typescript

Is there a way to maintain the user login attempts limit even after page refresh? login() { /* Check if user has fewer than 5 failed login attempts */ if (this.failedAttempts < 4) { this.auth.login(this.credentials).subscribe(() => { this.rou ...

What is the best way to utilize Union Types in v-model within a Vue component's :is directive?

I'm facing a TypeScript error while trying to bind the value of apiRes to v-model. Below is the code snippet where the error occurred. How can I resolve this issue? Arguments of type { modelValue: Cars | undefined; } cannot be assigned to type NonNull ...

Triggering multiple subscription functions in Ionic 3 NGRX when a single state change occurs

I have developed an Ionic 3 application that utilizes NGRX for state management purposes. The app is designed to connect to a device via BLE technology. Within my connection page, where the BLE device is connected, I have implemented the following code: ...

List the hours using TypeScript

My data table is displaying records including a column for hours spent and a row showing the total sum of those hours. While the hours are being added correctly, the minutes display as NaN, such as 52:Nan. Can someone assist me in resolving this issue? co ...

Angular: How forkJoin changes the behavior of Subjects

Hey everyone, can someone help me understand this situation? Here is the code that's working: this.sessionService.current$.subscribe(session => { console.log('WORKING', session); }); But this code is causing issues: forkJoin([ thi ...

Guidelines for creating a routing for a child component using Angular

Seeking assistance with setting up routing in an Angular application. I have a main component called public.component, and the auth.component component is inserted from the child module Auth.module using the selector. How can I configure the routing for th ...

Specify the type of nested object exclusively with string values

I am working on creating a complex nested object structure with string values only, as shown below: let obj = { foo: "bar", foo2: "bar2", nestedFoo: { foo3: "bar3", anotherNested: { foo4: "bar4" ...

Is there a way to customize the "instanceof" functionality for an ArrayBuffer?

I've been working on a project that involves using threejs to draw a filled polygon based on its vertices. Initially, I started with a square and was able to get it working perfectly on its own. However, the real issue arose when I tried to integrate ...

Find out if all attributes of the object are identical

I am trying to create the boolean variable hasMultipleCoverageLines in order to determine whether there are multiple unique values for coverageLineName within the coverageLines items. Is there a more efficient way to write this logic without explicitly c ...

Unable to update a single object within an array using the spread operator

I am currently working on updating an object within an array and have encountered some issues. In my initial code, I successfully updated a specific property of the object inside the array like this: var equipment = this.equipments.find((e) => e.id === ...