predict
The predict utility creates a Promise that can be aborted using an AbortController. It allows you to set a timeout for asynchronous operations and provides a way to gracefully cancel them before completion.
Implementation
View Source Code
ts
/**
* Creates a Promise that can be aborted using an AbortController.
*
* @example
* ```ts
* const slowFn = () => new Promise(resolve => setTimeout(() => resolve('slow'), 10000));
* const fastFn = () => new Promise(resolve => setTimeout(() => resolve('fast'), 5000));
*
* predict(slowFn); // rejects after 7 seconds
* predict(fastFn); // resolves with 'fast' after 5 seconds
* ```
*
* @param fn - The function to execute, which receives an AbortSignal.
* @param options - The options for the abortable function.
* @param [options.signal] - The AbortSignal to use for aborting the Promise.
* @param [options.timeout=7000] - The timeout in milliseconds after which the Promise will be aborted.
*
* @returns - A Promise that resolves with the result of the callback or rejects if aborted.
*/
export function predict<T>(
fn: (signal: AbortSignal) => Promise<T>,
options: { signal?: AbortSignal; timeout?: number } = {},
): Promise<T> {
const { signal, timeout = 7000 } = options;
const abortSignal = signal ? AbortSignal.any([AbortSignal.timeout(timeout), signal]) : AbortSignal.timeout(timeout);
return Promise.race([
fn(abortSignal),
new Promise<never>((_, reject) => {
abortSignal.addEventListener('abort', () => reject(new Error('Operation aborted')), { once: true });
}),
]);
}Features
- Isomorphic: Works in both Browser and Node.js.
- Abortable: Integration with
AbortSignalfor clean cancellation. - Timeout Support: Automatically aborts if the operation exceeds the specified timeout.
- Type-safe: Properly infers the return type of the executed function.
API
ts
function predict<T>(
fn: (signal: AbortSignal) => Promise<T>,
options?: {
signal?: AbortSignal;
timeout?: number;
},
): Promise<T>;Parameters
fn: An asynchronous function that receives anAbortSignaland returns a Promise.options: Optional configuration:signal: An externalAbortSignalto use for aborting the operation.timeout: Maximum time in milliseconds before the operation is aborted (defaults to7000).
Returns
- A Promise that resolves with the result of
fn. - Rejects with an "Operation aborted" error if the timeout is reached or the signal is aborted.
Examples
Basic Timeout Control
ts
import { predict } from '@vielzeug/toolkit';
const slowFn = (signal: AbortSignal) => new Promise((resolve) => setTimeout(() => resolve('slow'), 10000));
const fastFn = (signal: AbortSignal) => new Promise((resolve) => setTimeout(() => resolve('fast'), 5000));
predict(slowFn); // rejects after 7 seconds (default timeout)
predict(fastFn); // resolves with 'fast' after 5 secondsWith Custom Timeout
ts
import { predict } from '@vielzeug/toolkit';
const result = await predict(
async (signal) => {
const response = await fetch('/api/data', { signal });
return response.json();
},
{ timeout: 3000 },
);With External AbortSignal
ts
import { predict } from '@vielzeug/toolkit';
const controller = new AbortController();
const promise = predict(
async (signal) => {
// Your async operation here
return await fetchData(signal);
},
{ signal: controller.signal, timeout: 5000 },
);
// Abort from outside
controller.abort();Implementation Notes
- Uses
AbortSignal.timeout()andAbortSignal.any()for efficient timeout handling. - The function receives the combined abort signal that triggers on either timeout or external abort.
- The promise races between the function execution and the abort signal.