RxJs/Angular loading from multiple HTTP requests and updating model from each request

Jai

I have been using Angular/RxJS for a few weeks and have various models that are built from multiple REST requests which I have thus far achieved using switchMap(). Here is a simple contrived example (stackblitz: https://stackblitz.com/edit/angular-o1djbb):

import { Component, OnInit, } from '@angular/core';
import { Observable, of } from 'rxjs';
import { delay, switchMap } from 'rxjs/operators';

interface Order {
  id: string;
  itemName: string;
  details?: string;
}

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  order: Order;

  ngOnInit() {
    this.getOrderFromApi(123)
      .subscribe(item => this.order = item);
  }

  getOrderFromApi(id): Observable<Order>  {
    const item$ = this.getItemName(id);
    const fullItem$ = item$.pipe(
      switchMap(n => {
        console.log(`Got name: '${n}''`);
        return this.getDetails(n);
      },
        (nameReq, detailsReq) => ({ id: '123', itemName: nameReq, details: detailsReq })
      ));
    return fullItem$;
  }

  getItemName(id): Observable<string> {
    return this.fakeXhr('foo');
  }

  getDetails(itemName): Observable<string> {
    console.log(`Got details '${itemName}''`)
    return this.fakeXhr('Some details about foo');
  }

  fakeXhr(payload: any) {
    return of(payload)
      .pipe(delay(2000));
  }
}

And a simple template:

<p>
  item: {{order && order.itemName}}
</p>
<p>
  details: {{order && order.details}}
</p>

This works but the order info is not rendered until both requests complete. What I would like to happen is for the itemName to render as soon as it's available and then details to render when they become available. Hence taking advantage of the multiple values that Observables can emit. Eg:

// first value emitted:
{ itemName: 'foo', details: null }
// second value emitted:
{ itemName: 'foo', details: 'Some details about foo' }

I realise I could probably achieve this with a BehaviourSubject or using Redux (as I have in the past with React), but feel there is a simple solution I can't quite grasp due to the newness of all this for me.

fridoo

Use expand to emit the data from the first request straight away and subsequently do the second request.

expand will call the inner request recursively, getting the order from the last request as input, so we only execute the second request when the order has no details and end the recursion otherwise with an EMPTY Observable.

import { Observable, EMPTY } from 'rxjs';
import { map, expand } from 'rxjs/operators';

getOrderFromApi(id): Observable<Order> {
  return this.getItemName(id).pipe(
    map(itemName => ({ id, itemName, details: null } as Order)),
    expand(order => order.details
      ? EMPTY
      : this.getDetails(order.itemName).pipe(
        map(details => ({ id, itemName: order.itemName, details } as Order))
      )
    )
  );
}

https://stackblitz.com/edit/angular-umqyem

The returned Observable will emit:

  1. { "id": 123, "itemName": "foo", "details": null }
  2. { "id": 123, "itemName": "foo", "details": "Some details about foo" }

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Updating data from http request in Angular

Skip requests from HTTP Interceptors for login request

WSAPoll receiving multiple connection requests from the same client (before and after a HTTP request)

NodeJS getting data from multiple http requests

Multiple http requests with cancel request

Make a single HTTP request from multiple invocations

Generate multiple HTTP request from list values

Elm: How to use data from one HTTP request in subsequent requests

Forward http requests based on data from the request body

Combining arrays from multiple http.requests into one array

Aggregate results from multiple HTTP requests to a single list

Angular 4 combine data from multiple HTTP requests

How to prevent multiple http requests from firing all at once

Get data from multiple HTTP GET requests before returning

How to get http responses from multiple requests in the order they're recieved

Combined response from multiple HTTP request from a loop

property of User model from http request returns null

values from model are not updating to the view

Loading model from checkpoint is not working

Parallizing loading from a model in file

Rails: Loading Image from Model

logging http requests from aiohttp

Loading and updating rules from a database in Drools 6

How to retrieve multiple device attributes from a single HTTP request in Thingsboard?

iOS Loading images from HTTP

Calling multiple HTTP requests in a single HTTP request in Node.js

How to change HTTP Request Path for multiple HTTP Requests at once in Jmeter

Loading indicator on Http requests

Preventing Multiple Requests and Updating

TOP Ranking

  1. 1

    Failed to listen on localhost:8000 (reason: Cannot assign requested address)

  2. 2

    Loopback Error: connect ECONNREFUSED 127.0.0.1:3306 (MAMP)

  3. 3

    How to import an asset in swift using Bundle.main.path() in a react-native native module

  4. 4

    pump.io port in URL

  5. 5

    Compiler error CS0246 (type or namespace not found) on using Ninject in ASP.NET vNext

  6. 6

    BigQuery - concatenate ignoring NULL

  7. 7

    ngClass error (Can't bind ngClass since it isn't a known property of div) in Angular 11.0.3

  8. 8

    ggplotly no applicable method for 'plotly_build' applied to an object of class "NULL" if statements

  9. 9

    Spring Boot JPA PostgreSQL Web App - Internal Authentication Error

  10. 10

    How to remove the extra space from right in a webview?

  11. 11

    java.lang.NullPointerException: Cannot read the array length because "<local3>" is null

  12. 12

    Jquery different data trapped from direct mousedown event and simulation via $(this).trigger('mousedown');

  13. 13

    flutter: dropdown item programmatically unselect problem

  14. 14

    How to use merge windows unallocated space into Ubuntu using GParted?

  15. 15

    Change dd-mm-yyyy date format of dataframe date column to yyyy-mm-dd

  16. 16

    Nuget add packages gives access denied errors

  17. 17

    Svchost high CPU from Microsoft.BingWeather app errors

  18. 18

    Can't pre-populate phone number and message body in SMS link on iPhones when SMS app is not running in the background

  19. 19

    12.04.3--- Dconf Editor won't show com>canonical>unity option

  20. 20

    Any way to remove trailing whitespace *FOR EDITED* lines in Eclipse [for Java]?

  21. 21

    maven-jaxb2-plugin cannot generate classes due to two declarations cause a collision in ObjectFactory class

HotTag

Archive