DEV Community

Jan Küster 🔥
Jan Küster 🔥

Posted on

4 2

Create a JavaScript Promise with timeout

I found a few examples on the web that let Promises run with a timeout:

Both were already good ideas but I wanted some more control of their behaviour and therefore I want to share my modified version.

Code

const defaultMessage = 'promise.timedOut'

/**
 * Lets a promise race against a timeout. If the promise settles before the timeout then it will
 * be the one to use (no matter, whether it has been resolved or rejected).
 *
 * Otherwise the timeout promise will be used to either resolve to a message
 * or reject an error, depending on the used options.
 *
 * @param promise {Promise} the promise to race against the timeout
 * @param timeout {number=}  optional number of milliseconds until timeout, defaults to 1000ms / 1 sec
 * @param throwIfTimedOut {boolean=} optional flag to either reject (if true) or resolve (if false), defaults to false
 * @param message {string=} optional message to be resolved/rejected on timeout, defaults to 'promise.timedOut'
 * @return {Promise<Awaited<unknown>>}
 */
export const createTimedPromise = (promise, { timeout = 1000, throwIfTimedOut = false, message, details } = {}) => {
  let timeOut = undefined

  const race = Promise.race([
    promise,
    new Promise((resolve, reject) => {
      timeOut = setTimeout(() => {
        if (throwIfTimedOut) {
          const error = new Error(message || defaultMessage)
          // I often like to attach contextual information to errors.
          // This is up to you, whether to do this or not
          error.details = details
          return reject(error)
        }
        else {
          return resolve(message || defaultMessage)
        }
      }, timeout)
    })
  ])

  // always clear timeout to prevent weird behaviour
  race.finally(() => clearTimeout(timeOut))

  return race
}
Enter fullscreen mode Exit fullscreen mode

Usage

// all default
await createTimedPromise(new Promise((resolve, reject) => { ... }))

// custom timeout
await createTimedPromise(new Promise((resolve, reject) => { ... }), { timeout: 500 })

// reject if timedout
await createTimedPromise(new Promise((resolve, reject) => { ... }), { throwIfTimedOut: true })

// additional context
await createTimedPromise(new Promise((resolve, reject) => { ... }), { message: 'you lost', details: { foo: 'bar' } })
Enter fullscreen mode Exit fullscreen mode

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post →

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more