Search code examples
javascripttimeout

how to throw and catch error if function runs longer than n seconds


I have a function of the form:

async someFunction () {
  try {
    someStuff()
  } catch (err) {
    doSomeCleanup()
  }
}

Which gets called multiple times with workers from a queue. Now I have a new requirement that a worker should fail if it takes longer than 30 seconds to run this function with a given worker. My gut instinct was to whip up something like:

const timeoutCheck;
const time = new Date();
async someFunction () {
  try {
    timeoutCheck = setInterval(() => {
      if (new Date() - time > 30000) throw new Error("timeout");
    }, 2000);
    someStuff()
  } catch (err) {
    doSomeCleanup()
  } finally {
    clearInterval(timeoutCheck);
  }
}

But as I quickly learned the setInterval gets run outside the try/catch block so the error isn't caught inside the catch block but in the main app and the whole app crashes rather than just a worker failing. Is there a good way to contain this error in the try/catch block or another way to accomplish erroring into the try/catch block if the function runs more than 30 seconds?


Solution

  • You can use Promise.race()

    let stop = () => new Promise((_, reject) =>
                       setTimeout(reject, 2999, "rejected"));
    
    let fn = () => new Promise((resolve, _) =>
                     setTimeout(resolve, 3000, "resolved"));
                     
    let someStuff = data => console.log(data);
    
    let doSomeCleanup = err => console.error(err);
    
    Promise.race([fn(), stop()])
    .then(doSomeStuff, doSomeCleanup);