Polling http services using rxjs
12/08/2018
Sometimes you just gotta poll. With observables, polling is quite declarative and concise. In this example we are going to start a job on a server and poll until the job is completed. During the waiting we can do side effects like update a progress bar.
Example:
const options = {};
const url = "SOME_URL";
const pollingUrl = "SOME_POLLING_URL";
// this is the http request that will start the job on the server.
const startJob = this.http.post(
url,
options
);
/**
* declare a timer observable that fires every 500ms and starts at 0ms.
* on every event poll the server and subscribe to the result using switchMap.
* switchMap will also cancel pending requests if
* nothing is returned within the timer period.
* the final step is to filter out events that are not completed.
*/
const polling = (job: JobDTO) => {
return timer(0, 500).pipe(
switchMap(() => this.http.get(pollingUrl)),
// we could add a tap here to update any progress indicators.
filter((job: any) => job.state === "COMPLETED"),
take(1)
);
};
/**
* start the job, and begin polling.
* to map the starting observable to the polling observable we use concatMap.
* and there's a timeout so that we don't wait indefinitely.
* we transform the observable to a promise so that we can `await` it.
*/
return await startJob
.pipe(
concatMap((job) => polling(job).pipe(timeout(5000)))
tap(
(job) => {
// some side effect like:
// window.location.href = `${environment.SERVER_API_URL}${job.result.link}`
}
)
).toPromise();