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 API
. I'm calling an API
that can only send back 2k
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:
GET
request a query parameter reqMode=''
:reqMode
with a value
or done
.value
then I need to make the same request but send the reqMode
parameter with the value.done
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:
getRecords(){
let url = this.url + 'reqMode=';
return this.http.get(url)
.doWhile() //What would I do here
}
When trying to do .doWhile
with a Observable that is type Observable<response>
. I'm looking for any alternative using Observables for what I need to do.
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: http://plnkr.co/edit/w0DdepslTaKrLSB3aIkA
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
result.next(data);
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(() => {
console.log('done');
// Emit values from the buffer.
closeBuffer.next(null);
closeBuffer.complete();
});
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
So I made an example on how you can do this by using a wrapping observer
and using .repeat()
.
All the logic is in app.component.ts
Checkout this plunker
I left comments in the code, but essentially it will make an http request, it will increment a count, and then will make another request with a different query number. It will repeat until it reaches 5.
You will have to modify it so the "repeat condition" represents your logic.
Hope that helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With