Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Adds a timeout to a JavaScript promise, rejects if not resolved within timeout period
/**
* wraps a promise in a timeout, allowing the promise to reject if not resolve with a specific period of time
* @param {integer} ms - milliseconds to wait before rejecting promise if not resolved
* @param {Promise} promise to monitor
* @Example
* promiseTimeout(1000, fetch('https://courseof.life/johndoherty.json'))
* .then(function(cvData){
* alert(cvData);
* })
* .catch(function(){
* alert('request either failed or timedout');
* });
*/
function promiseTimeout(ms, promise){
return new Promise(function(resolve, reject){
// create a timeout to reject promise if not resolved
var timer = setTimeout(function(){
reject(new Error("promise timeout"));
}, ms);
promise
.then(function(res){
clearTimeout(timer);
resolve(res);
})
.catch(function(err){
clearTimeout(timer);
reject(err);
});
});
};
@0xFFFC

This comment has been minimized.

Copy link

commented Mar 25, 2019

When the timeout is reached, I think that we should not longer trigger the resolve or the reject function.

`let promiseTimeout = (ms, promise, step) => {
return new Promise(function(resolve, reject) {
// create a timeout to reject promise if not resolved

    let cleared = false;
    let timer = setTimeout(function() {cleared = true; reject(step + " time out");}, ms);

    promise
    .then(function(res){
        // If already cleared, the response is too late, we must not do anything
        if (! cleared) {
            clearTimeout(timer);
            resolve(res);
        }    
    })
    .catch(function(err){
        if (! cleared) {
            clearTimeout(timer);
            reject(err);
        }    
    });
});

};`

@jack-sf

This comment has been minimized.

Copy link

commented Jun 13, 2019

Some version with tweak to change the produced error and a onTimeout callback if you want to do something once timeout happens, also typescript added:

/**
 * Wraps a promise in a timeout, allowing the promise to reject if not resolved with a specific period of time.
 *
 * @example
 * wrapPromiseWithTimeout(1000, fetch('https://courseof.life/johndoherty.json'))
 *   .then(function(cvData){
 *     alert(cvData);
 *   })
 *   .catch(function(){
 *     alert('request either failed or timedout');
 *   });
 */
function wrapPromiseWithTimeout<T>(
  promise: Promise<T>,
  time: number,
  {
    error = () => new Error('promise timeout'),
    onTimeout,
  }: {
    error?(): Error;
    onTimeout?(): void;
  } = {},
) {
  return new Promise<T>((resolve, reject) => {
    const timer = setTimeout(() => {
      if (onTimeout) {
        onTimeout();
      }

      reject(error());
    }, time);

    promise
      .then(res => {
        clearTimeout(timer);
        resolve(res);
      })
      .catch(err => {
        clearTimeout(timer);
        reject(err);
      });
  });
}
@im-danwu

This comment has been minimized.

Copy link

commented Aug 15, 2019

Promises can only be settled once.

const bar = await new Promise(resolve => { resolve(1); resolve(2); }); here bar is 1

So you don't need all the clearTimeout or worry about race conditions 👍

function promiseTimeout(ms, promise) {
  return new Promise((resolve, reject) => {
    setTimeout(() => reject(new Error("promise timeout")), ms);
    promise.then(resolve).catch(reject);
  });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.