DEV Community

Cover image for Create Promises with Timeout Error in Typescript
Nikos Anifantis
Nikos Anifantis

Posted on • Updated on

Create Promises with Timeout Error in Typescript

Cover Photo by Immo Wegmann on Unsplash.

The Problem πŸ€”

Sometimes we create promises that take too long to finish and we don't want to wait. For example, if we want to make a request and the response takes 20 seconds to finish and for any reason we may want to throw an error in the first 5 seconds and proceed to the next code block.

In this article, we will see how to implement a promise which throws an error after a specific time span. It supports typings with the power of Typescript and accepts a custom error to be thrown when the time comes.

Implementation πŸš€

First of all, we create a new promise that rejects an error after a time span in milliseconds. The return type of the timeout promise is never which represents the type of values that never occur. For instance, never is the return type for a function expression or an arrow function expression that always throws an exception or one that never returns.

// create a promise that rejects in milliseconds
const timeout = new Promise<never>((_, reject) => {
  setTimeout(() => {
    reject(timeoutError);
  }, ms);
});
Enter fullscreen mode Exit fullscreen mode

The next step is to use Promise.race() which returns a Promise that fulfills or rejects as soon as one of the promises in an iterable fulfills or rejects, with the value or reason from that promise. Here you can see that we have used <T> generic type that it will be defined in our final function.

Promise.race<T>([anyPromise, anyOtherPromise]);
Enter fullscreen mode Exit fullscreen mode

Great, we saw all code blocks, let's see the full implementation below:

function promiseWithTimeout<T>(
  promise: Promise<T>,
  ms: number,
  timeoutError = new Error('Promise timed out')
): Promise<T> {
  // create a promise that rejects in milliseconds
  const timeout = new Promise<never>((_, reject) => {
    setTimeout(() => {
      reject(timeoutError);
    }, ms);
  });

  // returns a race between timeout and the passed promise
  return Promise.race<T>([promise, timeout]);
}
Enter fullscreen mode Exit fullscreen mode

As you can see, we have created a function that accepts the following arguments:

  • promise: our actual promise
  • ms: the maximum time in milliseconds which we want to wait
  • timeoutError: (optional) we may pass a custom error to throw after timeout

You can find the final source code in stackblitz:

Conclusion βœ…

Hooray, we made it to the end! I hope you enjoyed this post and do not wait for time consuming promises any more πŸ˜†.

Please support this article with your ❀️ πŸ¦„ πŸ”– to help it spread to a wider audience. πŸ™

Also, don’t hesitate to contact me if you have any questions leaving here your comments or Twitter DMs @nikosanif.

Top comments (3)

Collapse
 
carlo318 profile image
carlo318

Hi Nikos,
thanks for sharing this "trick".
I've just noticed a little imperfection in the full teoric example:
instead of: reject(timeout);
it should be: reject(timeoutError);

or am I wrong?
Thankyou again!
Carlo

Collapse
 
nikosanif profile image
Nikos Anifantis

Great catch! You are right! Although I have implemented right at Stackblitz, there is a typo in this article.

Collapse
 
nikosanif profile image
Nikos Anifantis

Thank you! I am happy to hear that.