I have 4 API calls first is to authenticate and than to upload a file and check file status. Once file status is return true than call API 4. Issue is with the fileStatus, I need to check file status till it is returned true and than only move, however, it just checks once and move to the next switchMap. Below is the code -
this.homeService.auth().pipe(
switchMap(authToken => {
return this.homeService.uploadFile(this.masterFile);
}),
// Check file status
switchMap(fileId => {
return this.homeService.fileStatus(fileId).pipe(
expand(status => {
if (status === true || retries >= 50) {
return of(status);
} else {
retries++;
return of(status).pipe(delay(2000), switchMap(() => this.homeService.fileStatus(fileId)));
}
}),
takeWhile(status => status === false && retries < 50, true),
catchError(error => throwError('Failed to confirm upload status after 50 retries'))
);
}),
switchMap((status: boolean) => {
if (status === true) {
return this.processFurther();
}
})
).subscribe(response => {
console.lot('All done');
}, error => {
console.log('Error processing ', error);
});
Your logic seems a bit complicated. Here's a function that will retry a set number of times with a delay that you can just plug into your stream.
function pollUntilResult<T>(
fn: () => Observable<T>,
matchFn: (value: T) => boolean,
retries: number,
delay: number = 0
): Observable<T> {
return timer(0, delay).pipe(
concatMap((_, index) => fn().pipe(map(value => ({ index, value }))) ),
takeWhile(({ index, value }) => index < retries && !matchFn(value), true),
last(),
map(({ value }) => value)
);
}
This function does the following:
Your observable stream should now look like this. (I don't know what was going on with the catchError/throwError business, but that made no sense to me, and since your last switchMap didn't return an observable for false results, I moved it in tehre).
this.homeService.auth().pipe(
switchMap(authToken => {
return this.homeService.uploadFile(this.masterFile);
}),
// Check file status
switchMap(fileId =>
pollUntilResult(() => this.homeService.fileStatus(fileId), 50, 2000)
),
switchMap((status: boolean) =>
(status === true) ? this.processFurther() : throwError('Failed to confirm upload status after 50 retries')
})
)