timeout

The timeout function wraps a function with a timeout. If the function does not complete within the specified time, the promise will be rejected.

1. Code

/**
 * Wraps a function with a timeout.
 * If the function does not complete within the specified time, the promise will be rejected.
 *
 * @template Return - The return type of the wrapped function.
 * @template Err - The error type that can be thrown by the wrapped function or the error callback.
 * @param {(...args: any[]) => Return} fn - The function to be wrapped.
 * @param {number} time - The timeout duration in milliseconds.
 * @param {(...args: any[]) => Err} [errCb] - Optional error callback function to handle timeout errors.
 * @returns {(...args: any[]) => Promise<Return>} - A wrapped function that returns a promise.
 */
const timeout = <Return, Err>(
  fn: (...args: any[]) => Return,
  time: number,
  errCb?: (...args: any[]) => Err
): ((...args: any[]) => Promise<Return>) => {
  return (...args: any[]) => {
    return new Promise<any>((resolve, reject) => {
      const timer = setTimeout(() => {
        if (errCb) reject(errCb(...args));
        else {
          reject(new Error("Function timed out"));
        }
      }, time);

      // Wrap fn call in Promise.resolve to handle both sync and async functions
      Promise.resolve(fn(...args))
        .then((result: Return) => {
          clearTimeout(timer);
          resolve(result);
        })
        .catch((err: Err) => {
          clearTimeout(timer);
          reject(err);
        });
    });
  };
};

export default timeout;

2. Installation

npx @jrtilak/lazykit@latest add timeout -ts

3. Description

The timeout function is a higher-order function that takes a function fn, a timeout duration time, and an optional error callback errCb as arguments. It returns a new function that, when called, returns a Promise. This Promise will resolve with the result of the fn function if fn completes within the specified time. If fn does not complete within the time, the Promise will be rejected. If an errCb function is provided, it will be called with the arguments passed to the wrapped function, and the Promise will be rejected with the result of errCb. If no errCb is provided, the Promise will be rejected with a new Error stating 'Function timed out'. The timeout function is designed to handle both synchronous and asynchronous functions, as it wraps the call to fn with Promise.resolve. This ensures that fn is always treated as a Promise, allowing the use of .then and .catch to handle the result or any errors.

4. Props

Prop

Type

Default Value

function*Function---
time*number---
errCbFunction---

5. Examples

import timeout from ".";

timeout(() => "Hello, World!", 1000);
// Expected Output: "Hello, World!"

timeout(() => new Promise((resolve) => setTimeout(resolve, 2000)), 1000);
// Expected Output: Error: Function timed out

timeout(
  () => new Promise((resolve) => setTimeout(resolve, 2000)),
  1000,
  () => console.log("I failed")
);
// Expected Output: I failed