Tips for chaining API calls in Angular using rxjs?

How can I efficiently nest API calls in Angular using RxJS?

  getProducts(): Observable<any> {
    return this.getProductIDs().pipe(
      map((response) =>
        response.products.map((data) => (item: any) =>
          flatMap(() => this.getProduct(item.id))
        )
      )
    );
  }


// With promises, we can use promise.all([])... How can I achieve something similar using RxJS?

However, the above method is producing the following output:

[ƒ, ƒ, ƒ, ƒ, ƒ, ƒ, ƒ]

If I try the following approach:

  getProducts(): Observable<any> {
    return this.getProductIDs().pipe(
      map((response) =>
        response.products.map((item: any) => this.getProduct(item.id))
      )
    );
  }

It results in:

[Observable, Observable, Observable, Observable, Observable, Observable, Observable]

Does anyone have a suggestion on how to map the results from one observable to a nested API call (returning an observable)?

NOTE

getProduct() is also an API call that returns an observable.

  getProduct(id): Observable<any> {
    return this.http.get<Observable<any>>(
      `http://localhost:4401/api/products/${id}`,
      {
        params: { id },
      }
    );
  }

Answer №1

Perhaps this is the solution you've been searching for. Without specifying your exact goal, the possibilities are vast:

This code snippet generates an array of objects (products) using IDs obtained from the getProductIDs function.

getProducts(): Observable<any> {
  return this.getProductIDs().pipe(
    map(res => 
      res.products.map(product => this.getProduct(product.id))
    ),
    switchMap(getProducts => forkJoin(getProducts))
  );
}

The same code can be written more succinctly by merging the map operation into the switchMap:

getProducts(): Observable<any> {
  return this.getProductIDs().pipe(
    switchMap(res => forkJoin(
      res.products.map(product => this.getProduct(product.id))
    ))
  );
}

If you prefer emitting each Product individually instead of in an array, here's an alternative approach:

getProducts(): Observable<any> {
  return this.getProductIDs().pipe(
    mergeMap(res => res.products),
    mergeMap(product => this.getProduct(product.id))
  );
}

A variation that produces an array again:

getProducts(): Observable<any> {
  return this.getProductIDs().pipe(
    mergeMap(res => res.products),
    mergeMap(product => this.getProduct(product.id)),
    toArray()
  );
}

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

Utilizing JSON data from Jade in local JavaScript: A comprehensive guide

Attempting to utilize a JSON object (the entire object, not just a portion) from Node via Jade in my local myScript.js. Here is what my Jade file looks like: span(class="glyphicon glyphicon-pencil" onclick="confirm(\"#{myJSON.taskid}\", \" ...

PlateJS: Difficulty in inserting images - Screen remains empty when trying to add images using the Image Element

I incorporated the Image Element component using the command npx @udecode/plate-ui@latest add image-element This action added the caption, media-popover, and resizable components to my setup. When referencing Platejs documentation, everything appears as ...

Is there a way to attach a JavaScript event to a textarea without directly accessing it?

I am curious about how to incorporate the following code: onblur="hcb.watermark.blur(event)" onfocus="hcb.watermark.focus(event)" style="color: rgb(136, 136, 136); into a textarea with the id "HCB_textarea" and the class "commentbox hcb-shadow-r," withou ...

React | What could be preventing the defaultValue of the input from updating?

I am working with a stateful component that makes a CEP promise to fetch data from post offices. This data is retrieved when the Zip input contains 9 characters - 8 numbers and a '-' - and returns an object with the desired information. Below is ...

The Project_Name index has not been defined

I'm attempting to tally up all of my projects in the project table, with Project_Name being a column name. Below is the code I've tested: <?php $sql = "SELECT COUNT(*) FROM project"; $result = $connection->query($sql); if ($res ...

A method to find the sum of the final n elements in an array by employing Arr.reduceRight

I have successfully calculated the sum of the last n elements in an array using a for loop. Is it possible to achieve the same result using Arr.reduceRight instead? x = [1,2,3,4,5]; y = 0 for(let i=x.length; i>x.length-3; i--) { console.log(x[i-1]); ...

Processing AJAX request without reloading the page using PHP

I need assistance with creating an image cropping tool that allows users to upload a picture, crop it, and display it on the page as an image.jpg rather than as base 64 (data:image). I have tried using HTML and JavaScript but it seems impossible, so now I ...

PHP: Dynamically update div content upon submission

I am attempting to update the "refresh" div after clicking the Submit button and also at regular intervals of 5 seconds. Despite looking through various resources, I have not been able to find a solution that meets my requirements. <script src="h ...

Receiving a k6 response that includes a JSON object with a lengthy integer value

During a performance test, I encountered an issue where the response contained items like: {"item":{"id":2733382000000000049}} When parsed using k6's response.json(), it appeared as : {"item":{"id":273338200000 ...

What is the best way to declare a global variable while making an asynchronous call using AngularJS?

Is there a way to utilize the single_video variable outside of the controller function? The issue arises when attempting to access it in the second console.log, as it returns an 'undefined' error due to asynchronousity despite successfully printi ...

MockStore has not been configured as a provider

My current challenge involves testing my app.component using Cypress. This component is supposed to fetch data from the ngrx store, and I've made sure to refer to the official documentation for guidance on setting up the test. Here's how the test ...

What strategies can we implement using Angular's change detection mechanism to enhance performance?

I'm embarking on my maiden voyage into the world of open source projects with a school gradebook. Despite being new to Angular, I'm facing a challenge regarding the runtime performance of the application. The generation of form controls dynamical ...

Is it possible to create an observable with RXJS that emits only when the number of items currently emitted by the source observables matches?

I am dealing with two observables, obs1 and obs2, that continuously emit items without completing. I anticipate that both of them will emit the same number of items over time, but I cannot predict which one will emit first. I am in need of an observable th ...

Instructions: Include the class 'active' only on the initial image within the gallery of images

<div class="placeImgCol "> <div class="slider-outer"> <img src="/images/arrow-left.png" class="prev" alt="Previous"> <img src="/images/arrow-right.png" class="next" alt="Next"> ...

What is the best method in JavaScript to create three different shades of a color?

My sass function generates lighter and darker versions of a base color, here is the code snippet: $colors: ( betpawa-green: #107A3D, lime-green: #8DC63F, yellow: #FBCD00, ); @mixin color-generator { @each $name, $hex in $colors { &-#{$nam ...

Having issues transferring the variable from JavaScript to PHP?

When attempting to pass a variable via AJAX request in JavaScript, I am encountering an issue where the variable is not being received in my PHP file. I'm unsure of where the problem lies. Can anyone help? JavaScript code var build = { m_count : ...

Why am I getting an error in Node's mongoose saying that the function is undefined?

I am currently in the process of developing a Node script that will establish a connection with an external server's MongoDB and add a new user. This is pretty basic stuff that I have encountered in numerous tutorials while using localhost. However, I ...

Tips for effectively using $interval for ongoing polling in AngularJS?

Within my Angular codebase, I have implemented long polling functionality using the following code snippet: var request = function() { $http.post(url).then(function(res) { var shouldStop = handleData(res); if (!shouldStop()) { ...

Executing a Jquery AJAX request to generate an authorization code

For my project requirement, I need to generate an authorization code by making a call to the O365 URL using jQuery's AJAX function. The script below is being triggered from the document ready() event. $.ajax({ ...

Is JavaScript not having an impact on your HTML code?

I am attempting to create a dynamic number change when the user interacts with the "range-slider" element, but the number is not updating as expected. Below is the code I have written: var rangeSlider = function() { var slider = $(".range-slider"), ...