Sometimes you have a request that doesn’t immediately return a response. For example, the user uploads some audio files and you process those and return them.
Using the Aurelia 2 Fetch Client, we are going to build an implementation that allows us to poll a specific endpoint and use callback functions to configure our response.
import { HttpClient } from '@aurelia/fetch-client';
export interface PollingOptions {
pollingIntervalMs?: number;
maxPollingAttempts?: number;
isSuccess?: (response: Response) => boolean;
parse?: (response: Response) => Promise;
}
export class PollingHttpClient {
private readonly httpClient: HttpClient;
private readonly defaultPollingIntervalMs = 1000;
private readonly defaultMaxPollingAttempts = 10;
constructor() {
this.httpClient = new HttpClient();
}
async pollUntilSuccess(
url: string,
options?: RequestInit,
pollingOptions?: PollingOptions
): Promise {
const pollingIntervalMs = pollingOptions?.pollingIntervalMs ?? this.defaultPollingIntervalMs;
const maxPollingAttempts = pollingOptions?.maxPollingAttempts ?? this.defaultMaxPollingAttempts;
const isSuccess = pollingOptions?.isSuccess ?? ((response) => response.ok);
const parse = pollingOptions?.parse ?? ((response) => response.json() as Promise);
let attempts = 0;
while (attempts < maxPollingAttempts) {
try {
const response = await this.httpClient.fetch(url, options);
if (isSuccess(response)) {
return await parse(response);
}
} catch (error) {
console.error('Fetch error:', error);
}
attempts++;
await new Promise(resolve => setTimeout(resolve, pollingIntervalMs));
}
throw new Error(\`Polling failed after ${maxPollingAttempts} attempts.\`);
}
}
To use it, simply instantiate it like you would the ordinary Fetch client:
const pollingClient = new PollingHttpClient();
async function fetchData() {
try {
const data = await pollingClient.pollUntilSuccess('https://api.example.com/data', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
}
}, {
pollingIntervalMs: 2000, // 2 seconds
maxPollingAttempts: 5,
isSuccess: (response) => response.status === 200, // Customize success condition
parse: async (response) => {
// Custom parsing logic, if needed
const result = await response.json();
// Further processing of result if necessary
return result;
}
});
console.log('Successfully fetched data:', data);
} catch (error) {
console.error('Failed to fetch data:', error);
}
}
fetchData();
In our example, a successful response is when the server returns a 200
status code to indicate a successful response.