Skip to main content

Async and await

async keyword

async keyword is placed before a function like so:

async function f() {
	return 1;
}

It basically make your function always returns a promise. If you didn't return a promise explicitly in the function they will be wrapped in a resolved promise automatically. The above async function is equivalent to the one below:

function f() {
	return Promise.resolve(1);
}

Async function are thenable because they return a promise object:

async function f() {
	return 1;
}

f().then(console.log); // prints out 1

It just ensures that the returned value is a promise 100% and enables await in the function body, that is all. Function is still executed as a normal function!

await keyword

You can only use await inside an async function, using it outside of an async function will result in a syntax error

The keyword await will make JavaScript wait until that promise settles and return the result of the resolved promise object as the value:

async function f() {
	let promise = new Promise((res, rej) => {
    	setTimeout(() => res("done"), 1000)
	});
    
    let result = await promise;
    console.log(result); // prints out done!
}

f();

await basically makes the function wait at the promise that you used it on and wait until the promise settles before moving on.

It will wait for another promise to resolve before moving on with its own execution.

The waiting doesn't cost any extra CPU time because since the function is marked asynchronous it can move onto executing other part of the code before resuming the execution after the promise you are awaiting is resolved.

Using await is just a more elegant syntax of executing .then, you wait until the promise is resolved before moving on. It is easier to read and write.

But you can only use await in a async function!

Error handling

If the promise resolves normally, await promise returns the result. But in the case of rejection, it will throw the error:

async function f() {
	await Promise.reject(new Error("oops"));
}

// Is equivalent to
async function f(){
	throw new Error("oops");
}

You can handle that error using try...catch

async function f() {

  try {
    let response = await fetch('http://no-such-url');
  } catch(err) {
    console.log(err); // TypeError: failed to fetch
  }
}

f();

If you don't handle it using try...catch inside the body of the function, then the async function itself will become rejected, and you can handle it by adding .catch to handle it.

If you forget .catch then you will get an unhandled promise error.

Why they are needed

If you are going to use async/await then you will rarely need to write promise.then/catch explicitly. async/await are based on promises.

Keep in mind that await doesn't work outside of non-async functions.

Example of call async from non-async

async function wait() {
  await new Promise(resolve => setTimeout(resolve, 1000));

  return 10;
}

function f() {
  // How do we call wait() and print out the result 10?
  // simple
  wait().then(val => console.log(val));
}

You would just have to treat wait as a promise object, remember async functions always return a promise object, and then just have to .then it to use the result after it is resolved.