Belajar JavaScript - Promise, async/await, dan Penanganan Error Asynchronous
Episode 16 of 23

Belajar JavaScript - Promise, async/await, dan Penanganan Error Asynchronous

Episode ini membedah mekanisme asynchronous JavaScript: state Promise, rantai .then dan .catch, sintaks async/await, serta Promise.all untuk eksekusi paralel. Kalian belajar menangani error asynchronous dengan benar dan menghindari callback yang berantakan.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Kode yang menunggu — fetch, setTimeout, baca file — sudah muncul di beberapa episode, tapi belum pernah dibedah. Episode 16 menjawab pertanyaan yang selalu tertunda: bagaimana JavaScript menangani pekerjaan yang hasilnya baru tersedia nanti? Jawabannya adalah Promise, dengan async/await sebagai cara modern menulisnya.

Promise muncul untuk memecahkan masalah callback hell: kode yang bersarang terlalu dalam karena setiap langkah menunggu langkah sebelumnya. Promise meratakan rantai itu, dan async/await membuatnya terbaca seperti kode synchronous biasa.

Episode ini adalah fondasi untuk semua aplikasi nyata — membaca API, menulis file, berkomunikasi dengan database. Kuasai state Promise, rantai .then dan .catch, async/await, lalu Promise.all untuk eksekusi paralel.

Promise dan State-nya

Apa Itu Promise

Promise adalah objek yang merepresentasikan hasil operasi asynchronous yang belum selesai. Dia punya tiga state:

  • pending: operasi masih berjalan.
  • fulfilled: operasi selesai dengan nilai hasil.
  • rejected: operasi gagal dengan alasan error.
JSMembuat Promise
const janji = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Berhasil diproses");
  }, 1000);
});
 
janji.then((hasil) => {
  console.log(hasil);
});

new Promise((resolve, reject) => menerima fungsi executor. resolve menandai keberhasilan dan reject menandai kegagalan. Di sini resolve("Berhasil diproses") dipanggil setelah satu detik, dan janji.then(...) menerima nilainya. Sebuah Promise hanya berpindah state satu kali — dari pending ke fulfilled atau rejected.

Reject dan Perbedaan dengan Sync Error

Jika operasi gagal, panggil reject. Perhatikan: error di dalam Promise tidak terlihat oleh try...catch biasa di luar — karena Promise berjalan asynchronous:

JSPromise yang gagal
const cek = new Promise((resolve, reject) => {
  const sukses = false;
  setTimeout(() => {
    if (sukses) {
      resolve("OK");
    } else {
      reject(new Error("Terjadi kegagalan"));
    }
  }, 500);
});
 
cek.catch((error) => {
  console.error("Ditangkap:", error.message);
});

reject(new Error("Terjadi kegagalan")) mengalihkan Promise ke state rejected. cek.catch(...) menangkapnya. Error async hanya bisa ditangkap lewat .catch, bukan try...catch synchronous yang ditempatkan di luar Promise.

Rantai .then dan .catch

Menyusun Langkah Berurutan

.then bisa dirantai: setiap .then menerima nilai dari .then sebelumnya dan mengembalikan nilai baru — termasuk Promise lain yang akan ditunggu:

JSRantai .then
function dapatkanPengguna() {
  return new Promise((resolve) => {
    setTimeout(() => resolve({ id: 1, nama: "Arman" }), 300);
  });
}
 
function dapatkanPosting(user) {
  return new Promise((resolve) => {
    setTimeout(() => resolve([`Posting dari ${user.nama}`]), 300);
  });
}
 
dapatkanPengguna()
  .then((user) => dapatkanPosting(user))
  .then((posting) => console.log(posting))
  .catch((error) => console.error(error));

.then((user) => dapatkanPosting(user)) mengembalikan Promise baru yang ditunggu oleh .then berikutnya — inilah cara menyusun langkah berurutan tanpa nesting. .catch di akhir menangkap error dari semua langkah sebelumnya. Satu .catch di ujung rantai jauh lebih bersih daripada banyak handler per langkah.

async/await

async menandai fungsi yang selalu mengembalikan Promise, dan await menjeda eksekusi hingga Promise selesai:

JSasync dan await
async function prosesLengkap() {
  const user = await dapatkanPengguna();
  const posting = await dapatkanPosting(user);
  return posting;
}
 
const hasil = await prosesLengkap();
console.log(hasil);

await dapatkanPengguna() menjeda prosesLengkap sampai Promise selesai, lalu meneruskan nilainya. Hasilnya sama dengan rantai .then, tapi terbaca seperti kode synchronous dari atas ke bawah — sedangkan rantai .then semakin bersarang seiring bertambahnya langkah. await hanya legal di dalam fungsi async.

Promise.all dan Penanganan Error

Eksekusi Paralel dengan Promise.all

await berurutan membuang waktu ketika beberapa Promise tidak saling bergantung. Promise.all menjalankan semuanya secara paralel dan menunggu semuanya selesai:

JSPromise.all untuk eksekusi paralel
async function muatDataParalel() {
  const [pengguna, posting, komentar] = await Promise.all([
    fetch("https://jsonplaceholder.typicode.com/users/1").then((r) => r.json()),
    fetch("https://jsonplaceholder.typicode.com/posts/1").then((r) => r.json()),
    fetch("https://jsonplaceholder.typicode.com/comments/1").then((r) => r.json()),
  ]);
 
  return { pengguna, posting, komentar };
}
 
const data = await muatDataParalel();
console.log(data.pengguna.name);

Promise.all([...]) menerima array Promise dan mengembalikan satu Promise yang selesai dengan array hasil dalam urutan yang sama. Ketiga fetch berjalan bersamaan, bukan berurutan. Jika salah satu gagal, Promise.all langsung rejected — hasil lain tidak dikembalikan.

Pola Penanganan Error Async

Untuk async/await, error ditangkap dengan try...catch biasa:

JStry catch pada async function
async function aman() {
  try {
    const respons = await fetch("https://jsonplaceholder.typicode.com/posts/1");
    if (!respons.ok) {
      throw new Error(`HTTP ${respons.status}`);
    }
    return await respons.json();
  } catch (error) {
    console.error("Gagal memuat data:", error.message);
    return { title: "Fallback" };
  }
}
 
console.log(await aman());

try membungkus operasi yang bisa gagal; catch (error) menangkap error dari await, termasuk yang dilempar oleh throw di dalam try. Mengembalikan nilai fallback di catch membuat fungsi tetap menghasilkan data yang bisa dipakai antarmuka — pola yang umum di production.

Tip

Pilih dengan niat: gunakan await berurutan untuk langkah yang saling bergantung, Promise.all untuk operasi independen yang ingin dijalankan paralel, dan Promise.allSettled jika kalian ingin tahu hasil setiap Promise meskipun ada yang gagal. Tiga pilihan ini mencakup hampir semua kebutuhan asynchronous.

Penutup

Episode 16 menuntaskan pemahaman asynchronous: state Promise yang berpindah dari pending ke fulfilled atau rejected, rantai .then dan .catch yang meratakan callback bersarang, sintaks async/await yang membuat kode terbaca berurutan, serta Promise.all untuk eksekusi paralel dengan try...catch yang bersih.

Inti yang harus dibawa pulang:

  • Promise punya tiga state: pending, fulfilled, dan rejected.
  • .catch menangkap error async; try...catch biasa tidak bisa menjangkau Promise.
  • async selalu mengembalikan Promise; await menjeda hingga selesai.
  • async/await lebih terbaca daripada rantai .then untuk langkah berurutan.
  • Promise.all menjalankan Promise independen secara paralel.
  • Tangani error async/await dengan try...catch dan beri fallback.

Di episode 17 selanjutnya kita akan membahas form validation dan interaksi pengguna — memvalidasi input dengan HTML5 dan JavaScript custom, menampilkan pesan error yang jelas, serta memproses submit form secara asynchronous. Kalian membangun form yang andal dan ramah pengguna.

Belajar JavaScript - Promise, async/await, dan Penanganan Error Asynchronous | Belajar JavaScript