Skip to content

Instantly share code, notes, and snippets.

@JakeSidSmith
Created December 20, 2018 16:07
Show Gist options
  • Save JakeSidSmith/fcd7a006ceb010cb6faca87bf769f827 to your computer and use it in GitHub Desktop.
Save JakeSidSmith/fcd7a006ceb010cb6faca87bf769f827 to your computer and use it in GitHub Desktop.
Class to ease process of polling an endpoint
import axios, { AxiosRequestConfig, AxiosError, AxiosResponse, CancelTokenSource } from 'axios';
interface PollOptions<PollResponse, CompleteResponse> {
interval: number;
shouldContinuePolling: (response: PollResponse | CompleteResponse) => response is PollResponse;
isComplete: (response: PollResponse | CompleteResponse) => response is CompleteResponse;
onStart?: () => any;
onStop?: () => any;
onError: (error: AxiosError) => any;
onComplete: (response: CompleteResponse) => any;
}
export class Poller<PollResponse, CompleteResponse> {
private axiosConfig: AxiosRequestConfig;
private options: PollOptions<PollResponse, CompleteResponse>;
private polling: boolean = false;
private timeout?: number;
private cancelTokenSource?: CancelTokenSource;
public constructor(axiosConfig: AxiosRequestConfig, options: PollOptions<PollResponse, CompleteResponse>) {
this.axiosConfig = axiosConfig;
this.options = options;
}
public start() {
if (!this.polling) {
this.polling = true;
this.startPoll();
if (typeof this.options.onStart === 'function') {
this.options.onStart();
}
}
}
public stop() {
if (this.polling) {
this.polling = false;
window.clearTimeout(this.timeout);
if (this.cancelTokenSource) {
this.cancelTokenSource.cancel();
}
if (typeof this.options.onStop === 'function') {
this.options.onStop();
}
}
}
private startPoll() {
this.cancelTokenSource = axios.CancelToken.source();
axios
.request({
...this.axiosConfig,
cancelToken: this.cancelTokenSource.token
})
.then(
(response: AxiosResponse) => {
if (this.options.shouldContinuePolling(response.data)) {
this.timeout = window.setTimeout(() => {
this.startPoll();
}, this.options.interval);
} else if (this.options.isComplete(response.data)) {
this.options.onComplete(response.data);
} else {
throw new Error('Polling was not complete, and should not continue');
}
},
(error: AxiosError) => {
if (axios.isCancel(error)) {
console.error('Polling cancelled');
} else {
this.options.onError(error);
}
}
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment