Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 6: Passing Observable response to another Observable

I have problem with fetching the web API output using observable in angular typescript.

I'd like to fetch the value that will be returned by the first observable then pass its value to another observable. So far, this is what I have written.

let output: any;
let output2: any;

_httpClient.get('http://localhost:5000/api/mycontroller')
  .subscribe((output_1) => {
    output = output_1;
  });

alert(output);

_httpClient.get('http://localhost:5000/api/mycontroller2'+output)
  .subscribe((output_2) => {
    output2 = output_2;        
  });
alert(output2);

I place an alert function below each observable subscribed to check the output returned of each response.

but when I execute it and check the output in the alert box, it gives undefined value to each.

how can I force observable to give the output that will come from my web API?

like image 803
aj go Avatar asked Jul 30 '18 20:07

aj go


2 Answers

You can use an operator such as switchMap which per documentation "Maps to observable, complete previous inner observable, emit values". Using switchMap it will switch to the 2nd HttpClient call mapping the first observable, when the source of the first HttpClient calls emits. If a new initial/outer request is executed, it will cancel the in-flight/in-process request.

Keep in mind, the way your alert() statements are set up, they will simply not work as alert() will execute before the requests have completed, hence the undefined. You'd need to execute alert() or similar within subscribe or utilize operators such as do/tap to ensure the data has actually been returned.

import { switchMap } from 'rxjs/operators';

_httpClient.get('http://localhost:5000/api/mycontroller')
  .pipe(
    switchMap(output => _httpClient.get('http://localhost:5000/api/mycontroller2' + output))
  )
  .subscribe(output2 => alert(output2));

If you need to save the outputs to some local class property, you can utilize do/tap to perform an action before/after data is returned/mapped/processed.

import { switchMap, tap } from 'rxjs/operators';

_httpClient.get('http://localhost:5000/api/mycontroller')
  .pipe(
    tap(output => {
        console.log(output);
        this.output = output;            
    }),
    switchMap(output => _httpClient.get('http://localhost:5000/api/mycontroller2' + output)),
    tap(output2 => {
        console.log(output2);
        this.output2 = output2;            
    })
  )
  .subscribe(output2 => alert(output2));
like image 126
Alexander Staroselsky Avatar answered Sep 19 '22 13:09

Alexander Staroselsky


For completeness of the accepted answer, other alternatives to switchMap should be mentioned as well.

In contrast to switchMap, the mergeMap (also called flatMap) operator will NOT be cancelled if the "outer observable" emits a second time before the "inner observable" completes. This may not be important in the case of HttpClient.get, because it typically only emits once, thus never triggering the inner observable again.

However, be aware of the difference between switchMap and mergeMap when continuing working with RxJS operators, especially when dealing with a sequential stream of data.

like image 22
ggradnig Avatar answered Sep 18 '22 13:09

ggradnig