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<T> { pollingIntervalMs?: number; maxPollingAttempts?: number; isSuccess?: (response: Response) => boolean; parse?: (response: Response) => Promise<T>; } export class PollingHttpClient { private readonly httpClient: HttpClient; private readonly defaultPollingIntervalMs = 1000; private readonly defaultMaxPollingAttempts = 10; constructor() { this.httpClient = new HttpClient(); } async pollUntilSuccess<T>( url: string, options?: RequestInit, pollingOptions?: PollingOptions<T> ): Promise<T> { 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<T>); 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<MyDataType>('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.