What is the await statement in Javascript

(Read this article on the blog) Recently I got a question regarding a Promise that had two awaits: // memo is a Promise await memo; await sleep(10); return (await memo) + e; Does having two awaits mean the Promise will be run twice? Or is it equal to this code: // memo is a Promise […]

(Read this article on the blog)

Recently I got a question regarding a Promise that had two awaits:

// memo is a Promise
await memo;
await sleep(10);
return (await memo) + e;

Does having two awaits mean the Promise will be run twice? Or is it equal to this code:

// memo is a Promise
const res = await memo;
await sleep(10);
return res + e;

To understand what happens, we need to look into what the await keyword does. And to do that, we first need to understand Promise states.

Promise states

FulfilledResolvedvalueRejectederrorPending

When a Promise is created it starts in the Pending state. It means it has no value yet.

It does not matter how the Promise is constructed, be it with the Promise constructor or calling an async function. In both cases, the Promise will be
Pending:

new Promise((res) => setTimeout(res, 100, "result"));
// Promise {<pending>}

(async () => {await fetch("https://advancedweb.hu")})();
// Promise {<pending>}

When the Promise is ready, it transitions to the Resolved or the Rejected state. Collectively, these are called Settled or Fulfilled. At this point, the
Promise has a value, either a result (if it is resolved) or an error (if it’s rejected).

A good illustration of how a Promise moves from Pending to Resolved is to wait a bit and print it again. In this code, the Promise resolves in 100ms, so the
second console.log sees it as Fulfilled:

const prom = new Promise((res) => setTimeout(res, 100, "result"));
console.log(prom);
// Promise {<pending>}

setTimeout(() => console.log(prom), 150);
// Promise {<fulfilled>: "result"}

The await keyword

So what does await do? It waits for the Promise to be Fulfilled (Resolved or Rejected) and returns (or throws) its value.

The simplest example is to store the result value then print it to the console:

const prom = new Promise((res) => setTimeout(res, 100, "result"));

(async () => {
	const res = await prom;
	console.log(res);
	// result
})();

First, prom is Pending, i.e. without a value. The await prom waits until the Promise becomes Resolved (the setTimeout calls
the res() function with "result") then returns the value.

You can think about that line as the await prom becomes the result of the Promise:

const res = await prom;
// when the Promise resolves, this line becomes:
const res = "result";

And what happens if the Promise is already Fulfilled? The await returns with the result without waiting.

Multiple awaits

To revisit the question from the beginning of this article, does the second await makes the code run slower?

// memo is a Promise
await memo;
await sleep(10);
return (await memo) + e;

When this code starts, memo is Pending. So the first await memo stops and waits for it to be Fulfilled. But when the second
(await memo) + e runs, memo already has a value, so it returns immediately.

Source: Advanced Web Machinery