Asynchronous Javascript 4 - Async/Await


Setelah menjelajahi Promise yang cukup memusingkan, kali ini Saya akan membahas sebuah sintaks yang membuat penggunaan Promise menjadi lebih indah, yaitu dengan async dan await.

Async

Sintaks async apabila ditaruh didepan sebuah fungsi, akan menjadikan nilai balik dari fungsi tersebut menjadi sebuah Promise, apapun nilainya.

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

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

kode diatas adalah sintaks yang dipermudah dari kode berikut

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

Await

Sintaks await dapat digunakan didalam suatu fungsi yang diawali dengan async. await memiliki satu tugas yaitu menunggu sampai suatu Promise selesai. Berikut adalah contoh penggunaan await untuk menunggu Promise selama 2 detik.

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();

Pada awalnya sintaks await hanya dapat digunakan didalam fungsi berawalan async. Namun pada standardisasi baru ES2022, terdapat fitur baru yaitu top level await. Fitur tersebut memungkinkan penggunaan sintaks await diluar fungsi async.

penanganan error async/await

Tanpa metode seperti catch(), sintaks async/await dapat menggunakan sintaks try/catch/finally untuk menangani error dan eksekusi callback saat Promise selesai.

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

cobaTangkapAkhirnya();

Atau, bisa juga dengan menggunakan metode then() dan .catch(), karena dengan menggunakan sintaks async, semua yang dikembalikan akan menjadi Promise.

Ketika menggunakan sintaks async/await pada sintaks blok try/catch, penggunaan await sebelum Promise tidak boleh ditinggalkan, karena nantinya jika terjadi penolakan, nilai dari penolakan tersebut tidak dapat diterima oleh blok catch.

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

cobaTangkap();

Hal ini dikarenakan blok try/catch telah ada jauh sebelum Promise muncul, sehingga memang sedari awal tidak didesain untuk menangani Promise. Blok catch memiliki fungsi untuk menangani synchronous error biasa seperti kode berikut:

try {
  throw new Error("waduh eror");
} catch (error) {
  console.log(error); // Error: waduh error
}

Penggunaan await sebelum suatu Promise akan menjadikan Promise seakan suatu proses synchronous, dan penolakan akan ditangani secara synchronous.

implementasi async await

Pada artikel Promise, suatu callback hell berhasil disederhanakan menjadi lebih ringkas dan mudah dibaca. Berikut adalah versi Promise menggunakan sintaks async/await.

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

Diakhir seri asynchronous Javascript ini Saya memiliki sebuah tantangan yang menggabungkan beberapa hal yang sudah dipelajari dari awal. Coba tes pemahamanmu dengan menebak output masing-masing skenario berikut.

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

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

Selamat, kamu telah berhasil menyelesaikan tutorial tentang asynchronous Javascript! Jangan lupa untuk terus memperdalam pemahamanmu dengan membaca atau menonton tutorial yang lain, semangat!

Referensi