Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the point of the await keyword within an async function in terms of returning a value?

I've researched many many posts and articles, and documentation. I'm seeking deeper understanding.

From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await

The await expression causes async function execution to pause until a Promise is settled, [...]

let fetchLocation = () => {
  //fetches information from satellite system and 
  //returns a Vector2 of lat long on earth
  return new Promise(resolve => {
    setTimeout(() => {
      resolve({
        lat: 73,
        long: -24
      });
    }, 2000);
  });
}

//async functions automatically return a promise.
let main = async() => {

  //awaits the promises resolution
  let result = await fetchLocation();
  console.log("I'm the awaited promise result", result)

  //immediately returns a promise as promise pending 
  return result;
}

console.log(main().then(res => console.log("I'm the original promise, just passed along by the async function, it didn 't a-wait for me", res)))

Before going down this rabbit hole, I knew async/await was syntactical sugar to make async code look synchronous.

I therefore fully expected to see main return the lat long coordinates. Instead it returns a promise.

A couple questions.

  1. Is the MDN documentation wrong? Does it not actually pause execution? It seems that the await keyword does not actually "pause" function execution... invoking main immediately returns a Promise<pending> object. However, after it returns we receive the value of the fulfilled promise in the awaited variable result. I suppose this came from the event loop? (And an async return statement is still synchronous.)

  2. So it seems that await unwraps a promise, and async wraps a promise, but you need to use await within async. I get that await might actually be promise.then() underneath the hood but if they want to make it fully synchronous in appearance, why not have the async function return the resolved promise value when used with await? Otherwise async await seems a bit redundant.

like image 493
vrspiration Avatar asked Oct 22 '25 00:10

vrspiration


2 Answers

Is the MDN documentation wrong?

No

Does it not actually pause execution?

It pauses the execution of the async function, hands a Promise back to the calling function — because it hasn't reached the point in the async function where it knows what to return — then the execution of the calling function (and the rest of the code) continues.

However, after it returns we receive the value of the fulfilled promise in the awaited variable result. I suppose this came from the event loop?

When the event loop stops being busy (running the code that called the async function in the first place and anything else that it picks up in the meantime) and the promise that was being awaited resolves, then the async function is woken up and given the resolved value of the function to continue processing.

why not have the async function return the resolved promise value when used with await?

Because that would block the entire event loop, which is why asynchronous logic (starting with callback style APIs) was introduced into JS in the first place.

Otherwise async await seems a bit redundant.

Consider a situation where you want to request a number of URLs from an API serially (so that you don't shove too many simultaneous requests at the API):

const data = [];
for (let i = 0; i < urls.length; i++) {
    const response = await fetch(urls[i]);
    const response_data = await response.json();
    data.push(response_data);
}

If you were to rewrite that without await then you'd probably end up with something recursive to count your way through the loop. It would be significantly more complex.

async/await makes dealing with complex combinations of promises simple, and simple promises trivial.

knew async/await was syntactical sugar to make async code look synchronous.

And it does that inside the async function and only inside it.

like image 63
Quentin Avatar answered Oct 24 '25 15:10

Quentin


It doesn't really pause the function, it just allows you to write the rest of the function code as if it were. But it's really just wrapping the rest of the code of the function into a .then().

E.g.

await foo = someFunc();
console.log(foo);

is executed like

someFunc().then((foo => {
    console.log(foo);
});

Since it's really still asynchronous, you can't return the resolved value, because the original calling function returns immediately. But if the calling function is also declared async, it returns a Promise, and the caller can either use await again (so it appears to be synchronous) or use .then().

like image 37
Barmar Avatar answered Oct 24 '25 14:10

Barmar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!