7

I wanted to know , how long will await wait [and hence keeps every resource in RAM] in an async function. Consider this example:

async function my_func(some_big_sized_data){
 let db_input = await gettingDBinputWhichIsDamnedSlow();
//then do some processing based on db_input and some_big_sized_data
}

Now what if DB keeps taking forever in replying. How long will await function wait and hold all those data [and hold up RAM in the process]? Is there a timeout of await too , or await can wait pratically infinitely ? [how to control this timeout time]

Anurag Vohra
  • 1,781
  • 12
  • 28

2 Answers2

13

await is practically a syntax sugar to consume promise. And promise can stuck pending forever, so does await. There's no builtin timeout mechanism for async/await.

Example:

async function foo() {
  await new Promise(r => r);
  console.log('complete');
}

If you run this foo function, that await is never gonna resolve, so it never reaches console.log('complete').

But await per se doesn't hold up RAM. Whether some resources stay in RAM or got GC'ed is determined by reference count, such mechanism is not related to await.

I said there's no builtin timeout mechanism for async/await. However, since it's just syntax sugar for promise, you can wrap your gettingDBinputWhichIsDamnedSlow promise within another promise to create ad hoc timeout control manually.

await new Promise((resolve, reject) => {
  const timeoutId = setTimeout(() => {
    reject(new Error('timeout')) 
  }, 10000) // wait 10 sec

  gettingDBinputWhichIsDamnedSlow().then(value => {
    clearTimeout(timeoutId)
    resolve(value)
  })
})
hackape
  • 18,643
  • 2
  • 29
  • 57
  • 1
    Regarding the first example, while `count` indeed can't be GCed because of the setInterval callback, both Promises can be, nothing holds any reference to it. – Kaiido Apr 15 '20 at 03:19
4

There is no way you can have a timeout for await, it would block as long as the Promise takes to get settled.

You can write your own function to get the timeout behavior, by simply using the Promise.race API.

The Promise.race from the docs:

The Promise.race() method 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.

function gettingDBinputWhichIsDamnedSlow() {
  return new Promise((res, rej) => setTimeout(res, 5000, "data from db"));
}

//takes timeout in ms
function awaitWithTimeout(timeout, ...args) {
  function timeOut() {
    return new Promise((res, rej) => setTimeout(rej, timeout, new Error(`Timed out after ${timeout}ms`)));
  }
  return Promise.race([...args, timeOut()]);
}

async function my_func(some_big_sized_data) {
  let db_input = null;
  try {
    db_input = await awaitWithTimeout(1000, gettingDBinputWhichIsDamnedSlow());
  } catch (error) {
    console.error(error.message);
  }
  console.log("db_input", db_input);
}

my_func();
Fullstack Guy
  • 16,368
  • 3
  • 29
  • 44