I need to make a series of calls to an API. Here is what should happen:
This is what I have so far, but it does not work and does not include the third call.
this.firstCall(formData)
.pipe(
interval(3000)
.pipe(
switchMap(res => {
this.secondCall(res)
.pipe(
catchError(error => {
return of(null);
})
)
}),
takeUntil(res => res.code !== 'P'),
timeout(21000)
)
)
.subscribe({
next: (data) => {
console.log('SUCCESS DATA', data)
},
error: (error) => {
console.log('PROCESSING ERROR', error)
}
})
We can use expand
to recursively call the second API, until we achieve C
(Complete), then we trigger the third API.
I am assuming the third API does not return an object with the property code. I use this assumption to break the expand
using EMPTY
which immediately completes the stream.
I use filter
operator to block out the emissions where code is P
.
import { of, expand, switchMap, EMPTY, delay, filter } from 'rxjs';
let i = 0;
const firstAPI = () => of('123');
const secondAPI = (id: any) => {
console.log('second API called');
i++;
return i > 10 ? of({ code: 'C' }) : of({ code: 'P' });
};
const thirdAPI = (id: any) => of(`hello ${id}`);
firstAPI()
.pipe(
switchMap((id: any) =>
secondAPI(id).pipe(
// we use expand to recurisvely call the second API.
expand((val: any) => {
// when the third API gets call use some property to break the expand loop
if (!val?.code) {
// immediately complete the stream
return EMPTY;
}
// it is still processing so call the second api again with a small delay
if (val.code === 'P') {
return secondAPI(id).pipe(delay(500));
} else if (val.code === 'E') {
// an error has occoured, so we can throw an error, feel free to add a catchError in the stream.
throw new Error('Some Error Occoured');
} else {
// the second API is completed so trigger the third API.
return thirdAPI(id);
}
}),
filter((item: any) => item?.code !== 'P')
)
)
)
.subscribe({
next: (data: any) => {
console.log('SUCCESS DATA', data);
},
error: (error: any) => {
console.log('PROCESSING ERROR', error);
},
});