inspired inspired - 1 year ago 57
TypeScript Question

Observable Continue calling API and changing parameters based on condition

I've read the Rx.js repeat Documentation in an effort to find out how I can continue calling an api based upon the response that I receive from the

. I'm calling an
that can only send back
records at a time. The API will send back a value for me to send it so that I can continue receiving the records until they return a done value.

So the flow goes as follows:

  1. Make a
    request a query parameter

  2. retrieve response with the last array containing
    with a

  3. If I receive a
    then I need to make the same request but send the
    parameter with the value.

  4. If i receive
    then I'll stop and return all of the records since the first call.

I get the first set of values when
subscribing normally
, but this would be my attempt after reading the docs, but it doesn't make sense:

let url = this.url + 'reqMode=';
return this.http.get(url)
.doWhile() //What would I do here

When trying to do
with a Observable that is type
. I'm looking for any alternative using Observables for what I need to do.

Answer Source

I don't think repeat() is a good operator for this. If I understand you correctly you want to repeat the HTTP request based on the response of the previous request. Operator repeat() is good if you wanted to repeat the same request multiple times.

I'd use concatMap() and recursively call itself until the reqMode is eqaul to "done":

See live demo:

import {Observable, Subject} from 'rxjs';

const result = new Subject();
const closeBuffer = new Subject();
const buffer = result.buffer(closeBuffer.asObservable());

function sendHttpRequest(reqMode) {
  return Observable.of('{"reqMode":' + reqMode + '}')
    .map(response => JSON.parse(response))
    .concatMap(data => {
      console.log('HTTP Response:', data);
      // Add data to the buffer of results;

      if (data.reqMode == 'done') {
        // Return an empty value wrapped as an Observable so concatMap can work
        // with it and emit onNext when it completes (which is immediately
        // thanks to the `.of()` operator).
        return Observable.of(null);
      } else {
        // Simulate that the next call returns 'done'
        return sendHttpRequest('"done"');

        // Uncomment this for real usage
        //return sendHttpRequest(data.reqMode);

// Subscribe to the buffer where I'll receive the value.
buffer.subscribe(val => console.log('Next: ', val));

// Simulate HTTP request with reqMode = 42
sendHttpRequest(42).subscribe(() => {
  // Emit values from the buffer.;

I use of() operator to simulate a request and to return a value wrapped as an Observable. I also use Subject to hold all responses that are buffered using buffer() operator. The I subscribe to the buffer to get the final array of responses (If you wrap this code into a function you'll most likely return the buffer where you can subscribe later).

The response is following:

HTTP Response: Object {reqMode: 42}
HTTP Response: Object {reqMode: "done"}
Next:  [Object, Object]

See similar question: Angular 2 + rxjs - how return stream of objects fetched with several subsequent http requests

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download