Back to posts
3 min read

Asynchronous Javascript 4 - Async/Await

After exploring Promise which is quite confusing, this time I will discuss a syntax that makes the use of Promise more beautiful, namely with async and await.

Async

The async syntax when placed in front of a function, will make the return value of that function become a Promise, whatever its value.

async function jamBerapa() {
  return new Date();
}

const jam = jamBerapa();
console.log(jam); // Promise {<fulfilled>: currentTime}

the code above is a simplified syntax from the following code

function jamBerapa() {
  return new Promise((resolve) => {
    resolve(new Date());
  });
}

Await

The await syntax can be used inside a function prefixed with async. await has one purpose: to wait until a Promise completes. Here is an example of using await to wait for a Promise for 2 seconds.

function sleepWithValue(ms, value) {
  return new Promise((resolve) => setTimeout(() => resolve(value), ms));
}

async function jamBerapaPlus() {
  const result = await sleepWithValue(2000, "selesai!");
  console.log(result); // "selesai!!"
}

jamBerapaPlus();

Initially the await syntax could only be used inside functions prefixed with async. However, in the newer ES2022 standard, a new feature called top level await was introduced. This feature allows the use of the await syntax outside of async functions.

Error Handling in async/await

Without methods like catch(), the async/await syntax can use the try/catch/finally syntax to handle errors and execute a callback when the Promise completes.

async function cobaTangkapAkhirnya() {
  try {
    await Promise.reject("Ups salah :(");
  } catch (error) {
    console.log(error);
  } finally {
    console.log("selesai");
  }
}

cobaTangkapAkhirnya();

Alternatively, you can also use the then() and .catch() methods, because when using the async syntax, everything returned becomes a Promise.

When using async/await syntax inside a try/catch block, the await before the Promise must not be omitted — otherwise, if a rejection occurs, the rejection value cannot be caught by the catch block.

async function cobaTangkap() {
  try {
    Promise.reject("Ups salah :(");
  } catch (error) {
    console.log(error);
  }
}

cobaTangkap();

This is because the try/catch block existed long before Promises were introduced, so it was never designed to handle Promises from the start. The catch block is meant to handle regular synchronous errors like the following code:

try {
  throw new Error("oops, an error");
} catch (error) {
  console.log(error); // Error: oops, an error
}

Using await before a Promise makes the Promise behave as a synchronous process, and rejections will be handled synchronously.

Implementing async/await

In the Promise article, a callback hell was successfully simplified into a more concise and readable form. Here is the Promise version rewritten using async/await syntax.

const baseUrl = "https://jsonplaceholder.typicode.com";

async function fetchUser() {
  try {
    // mendapatkan data komentar
    const commentsResponse = await fetch(baseUrl + "/comments/1");
    const comments = await commentsResponse.json();
    // mendapatkan data post
    const postResponse = await fetch(baseUrl + "/posts/" + comments.postId);
    const post = await postResponse.json();
    // mendapatkan data user
    const userResponse = await fetch(baseUrl + "/users/" + post.userId);
    const user = await userResponse.json();
    
    console.log(user);
  } catch (error) {
    console.log(error);
  } finally {
    console.log("promise end...");
  }
}

console.log("code starting...");
fetchUser();
console.log("code finishing...");

Quiz

At the end of this asynchronous Javascript series, I have a challenge that combines several things learned from the beginning. Try testing your understanding by guessing the output of each scenario below.

import { sequentialStart } from "./scenario1";
//import { sequentialWait } from "./scenario2";
//import { concurrent1 } from "./scenario3";

sequentialStart();
// sequentialWait();
// concurrent1();

Congratulations, you have successfully completed the tutorial on asynchronous Javascript! Don’t forget to keep deepening your understanding by reading or watching other tutorials — keep it up!

References