Send a query to the API, adjust the output, and then proceed to another API request

Today marks my first time not as a reader, but seeking advice after grappling with RxJS for two whole days.

The task at hand involves firing off two API calls: the initial call fetches a list of pricelists. The response takes the form of an object with IDs serving as keys. Here's a snippet for reference:

{
    "a64cb186455a5a0b5ea1f12e027ce384": {
        "supplier_name": "Supplier_1",
        "pricelists": [
            {
                "status": "enabled",
                "title": "Pricelist_1",
                "pricelist_id": "839b47d67954a9dec375a40652f93b52",
            },
            {
                "status": "expired",
                "title": "Pricelist_2",
                "pricelist_id": "1aed04c948bc63e3b6f8100b0e410afd",

            }
        ]
    }
}

My goal is to extract only the array of pricelists from this object. Subsequently, I need to filter these pricelists to retain only the enabled ones. Following this filtering process, I check if there are any pricelists left. If so, I store all pricelists in an array and designate the first one as the selected pricelist.

With the selected pricelist in hand, the next step involves fetching the wines associated with this pricelist using its unique identifier through another API call. A glimpse into the response looks something like this:

[
   {
       "producer": "Producer_1",
       "id_prod": "90e2ac8275a68d9eb3a246735e7546cd",
       "wines": [
           {...},
           {...},
           {...},
           {...}
       ]
   },
   {
       "producer": "Producer_2",
       "id_prod": "54e2bf8275a68d9eb3a246735e7546zq",
       "wines": [
           {...},
           {...},
           {...},
           {...}
       ]
   }
]

Subsequently, I seek to consolidate all objects within the "wines" keys into a single array for efficient looping on the HTML side.

Furthermore, a modal exists for altering the selected pricelist. Leveraging the stored pricelists enables me to switch between them. Whenever the active pricelist changes, it necessitates a fresh API request to load the corresponding wines.

I've managed to implement the code thus far, albeit nested subscriptions that feel somewhat inelegant. Hence, I yearn to refactor the structure in a more streamlined manner, and I present the existing code snippet below for clarity:


  // Existing code here

In essence, I strive to restructure the above code employing an RxJS approach. Any insights or tips would be greatly valued, as I find myself at a loss here!

Despite my attempts with RxJS, though successful in obtaining pricelists and their associated wines, transitioning between active pricelists remains unresponsive with no HTML updates. Clarity eludes me regarding RxJS operations, accentuating the urgency of your guidance.

Answer №1

Tried to start working on this but got overwhelmed with the complexity of the question.

Check out the Stackblitz link to see where I left off.

Suggestion: Consider adding proper types for better clarity.

type PriceListStatus = 'enabled' | 'expired';
type PriceList = {
  status: PriceListStatus;
  title: string;
  pricelist_id: string;
};
type SupplierData = {
  supplier_name: string;
  pricelists: Array<PriceList>;
};
type PriceListData = Record<string, SupplierData>;
type WineData = {
  producer: string;
  id_prod: string;
  wines: any[]; // add specific type here!
};

In RxJs, it's crucial to use piping and subscribe only at the endpoint to maintain a continuous flow from source to sink.

const dataToPriceListIds$ = of(PRICE_LIST_DATA).pipe(
  // Extract array of pricelists and filter enabled ones
  map((data) => mapToPriceIds(data, 'enabled')),
  debugPipe('Filtered price ids'),
  // Check if there are any pricelists remaining
  filter(isArrayLengthGreaterThanZero),
  debugPipe('Only emit if array greater than zero')
);

const selectedPriceListId$ = dataToPriceListIds$.pipe(
  // Select the first pricelist from the filtered array
  map((arr) => arr[0]),
  debugPipe('First item of the array')
);

const wineData$ = selectedPriceListId$.pipe(
  // Simulate API call using the selected id
  switchMap((id) => of(WINE_DATA).pipe(delay(300))),
  debugPipe('Wine data')
);

wineData$.subscribe();

Answer №2

Have you considered using the MergeMap operator in RXJS?

With mergeMap, you can receive the result from your initial API request and make a second API call immediately after.

Here is an example of how to use it:

this.service1.Request1()
        .pipe(
            take(1),
            mergeMap(response1 => 
                this.service1.Request2(response1).pipe(
                    take(1),
                    map(response2 => {
                        console.log(response1);
                        console.log(response2);
                    })
                )
            )
        )

If I understand correctly, your goal is to make two sequential API calls based on the outcome of the first one.

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

Struggling to synchronize the newly updated Products List array in zustand?

Let me clarify the scenario I am dealing with so you can grasp it better. I have a Cart and various Products. When a user adds the product (product_id = 1) twice to the cart with the same options (red, xl), I increase the quantity of that item. However, i ...

Terminate all active service requests and retrieve only the outcomes from the most recent request

Is there a way to cancel ongoing requests and only retrieve the result of the latest request triggered by my service on the backend? Here's my current code: this.vehiclesService.getVehiclesByPage(currentState).subscribe(success => { this.c ...

Updating Your Child: A Guide

Currently, I have a component that makes reference to a child component with the following code cc: TheChildComponent; @ViewChild('theChildComponent') set details(content: TheChildComponent) { this.cc = content; }; TheChi ...

Validating Angular for controls that are not in a form

I am working on validating a form using reactive form group for non-form controls. As part of my form, I am incorporating custom components. Take a look at the example below: <form [formGroup]='formGroupName' > <input type='text&a ...

Perform multiple HTTP requests in Angular2 based on the responses of previous requests

For my Angular 2 application, I am faced with the task of making multiple HTTP calls. The process involves making a call, waiting for the response, extracting the URL for the next call from that response, and then initiating the subsequent call. This chain ...

Using regular expressions, you can locate and replace the second-to-last instance of a dot character in an email address

I'm looking to replace the second last occurrence of a character in a given string. The length of the strings may vary but the delimiter is always the same. Here are some examples along with my attempted solutions: Input 1: james.sam.uri.stackoverflo ...

What is the best way to configure React children to only allow for a single string input

When using this component: <Component>example string</Component> How can I avoid the Typescript error related to type children: "example string" causing an issue? The 'children' prop of this JSX tag expects type '&qu ...

Troubles with Type Inference in Typescript Conditional Types

Explore the Unique Playground Given a specific type: export declare type CustomFilter<T> = { [P in keyof T]?: (P extends keyof T ? T[P] : any); }; Encountering an issue when defining the filter as follows: update.$setOnInsert.createdAt = new Date ...

Creating instance methods in a TypeScript object can be accomplished by defining the methods within the object's class definition. When the object is

As a seasoned Java developer, I've recently been dabbling in TypeScript. Let me introduce you to my user object: export class User { id: string; name: string; email?: string; unit: string; street: string; postalcode: string; ...

Launching ngx-modal in Angular2 without the need for a button click

As a newcomer to Angular2, I am seeking guidance on how to trigger an alert Modal in the event of a failed login within my code. While most examples I have come across rely on a button click, I am wondering if it is possible to achieve this based on the st ...

Unable to assign a value to an undefined property in TypeScript

I need to store data in an object and then add it to another object let globalSamples = {} as any; let sample = { } as ISamplesDetail []; sample = []; for (let i = 0 ; i<this.prelevementLingette.samplesDetail.length; i++) { sample [i].id= thi ...

Building a hierarchical tree structure using arrays and objects with Lodash Js

I am attempting to create a tree-like structure using Lodash for arrays and objects. I have two arrays, one for categories and the other for products, both with a common key. The goal is to organize them into a tree structure using string indexing. let ca ...

cssclassName={ validatorState === RIGHT ? 'valid' : 'invalid' }

Is there a way to dynamically add different classes based on validation outcomes in React? My current implementation looks like this: className={ validatorState === RIGHT ? 'ok' : 'no' } However, I also need to handle cases where the ...

A guide to troubleshooting the "Cannot resolve all parameters error" in Angular

Recently delved into the world of angular 2, and I've come across my first challenge. I'm trying to establish a service for retrieving data from a server but I keep encountering this particular error Error: Can't resolve all parameters fo ...

What is the best way to incorporate a routerLink in an HTML string?

For my app, I need to display a long piece of text using HTML strings. Here is an example: // component description: string = `<p>Hello world. <a routerLink="/home">Click here</a> to go to the home page.</p>`; // template <div ...

An issue has been identified: the element 'insight-dashboard-erneuerung-settings' is unrecognized during the implementation of lazy loading

I am currently working on implementing lazy loading for the Dashboard module in my Angular project, but I have run into an issue: When trying to use 'insight-dashboard', I am getting the error message 'is not a known element'. I have c ...

Using typescript, encountering an issue with dynamic import and json file integration

When creating a function to retrieve test data for multiple environments, I encountered an issue: export class DataHelper { public static async getTestData(fileName: string): Promise<any> { return await import(`../${fileName}`); } } Running ...

JS/TS Strategies for Sharing Code Across Multiple Projects

Perhaps there is a different approach that has not crossed my mind. I have spent some time exploring various methods like js/ts with npm link, git submodules, tsconfig paths, symlink, npm/pnpm/yarn workspace, npm pack & npm link, package.json exports, ...

Manipulating a MongoDB object using node.js

Within my server.js file, I have defined a database model to be used for a POST request: var department = mongoose.model('department', { departmentName: String, rooms: [{ roomNumber: String, width: Number, height: Number, pos ...

When all observables have finished, CombineLatest will only execute one time

I've encountered a problem that requires me to use a combination of 3 route observables to open a modal. Here is the logic in my code: combineLatest([obs1, obs2, obs3]) .subscribe(([s1, s2, s3]: any) => { openModal(); }); The issu ...