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);
});
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]);
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]);
}
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)
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
Great catch! You are right! Although I have implemented right at Stackblitz, there is a typo in this article.
Thank you! I am happy to hear that.