Memahami Promises & Fetch API dalam JavaScript

Dalam JavaScript, ketika kita berurusan dengan data yang membutuhkan waktu untuk diproses, seperti mengambil informasi dari server atau membaca file, kita menggunakan Promise. Salah satu cara paling umum untuk bekerja dengan Promise adalah menggunakan Fetch API untuk mengambil data dari internet.

Apa itu Promise?

Promise adalah objek yang mewakili sebuah proses yang sedang berjalan (asynchronous) dan akan selesai di masa depan dengan hasil tertentu. Hasil tersebut bisa berupa sukses atau gagal.

Promise memiliki tiga status utama:

  • Pending β†’ Proses masih berlangsung.

  • Fulfilled β†’ Proses berhasil dan mengembalikan nilai.

  • Rejected β†’ Proses gagal dan mengembalikan error.

Contoh membuat promise:

let janji = new Promise((resolve, reject) => {
  let sukses = true;
  if (sukses) {
    resolve("Berhasil");
  } else {
    reject("Gagal!");
  }
});

console.log(janji); 
// Output: Promise { 'Berhasil' }

πŸ“Œ resolve() digunakan jika berhasil, sedangkan reject() digunakan jika terjadi kesalahan.

Menggunakan .then() dan .catch() dalam Promise

Agar kita bisa menangani hasil dari Promise, kita menggunakan .then() untuk hasil sukses dan .catch() untuk menangani error.

janji
  .then((pesan) => {
    console.log("Sukses:", pesan);
  })
  .catch((error) => {
    console.log("Error:", error);
  });

// Output: 
// Sukses: Berhasil

Membuat Promise Manual (Tanpa Fetch API)

Kita bisa membuat Promise sendiri tanpa menggunakan fetch() atau API.

Contoh:

function cekKetersediaanStok(stok) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (stok > 0) {
        resolve("Stok masih tersisa.");
      } else {
        reject("Stok habis.");
      }
    }, 1500);
  });
}

cekKetersediaanStok(5)
  .then((result) => {
    console.log("Hasil Stok: ", result);
  })
  .catch((error) => {
    console.log("Hasil Stok:", error);
  });

Hasil:

// Jika pada argument cekKetersediaanStok kita beri nilai: 5 
Hasil Stok:  Stok masih tersisa.
// Namun, jika pada argument cekKetersediaanStok kita beri nilai: 0
Hasil Stok:  Stok habis.

Promise vs Callback

Sebelum ada Promise, kita menggunakan Callback untuk menangani proses asinkron. Tapi, callback bisa menyebabkan callback hell (struktur kode menjadi berantakan).

function pesanMakan(callback) {
    setTimeout(() => {
        console.log("πŸ• Makanan dipesan...");
        callback();
    }, 1500);
}

function bayarMakan(callback) {
    setTimeout(() => {
        console.log("πŸ’ΈMakanan dibayar...");
        callback();
    }, 2000);
}

pesanMakan(() => {
    bayarMakan(() => {
        console.log("Selesai, selamat makan...");
    })
});

Penjelasan:

Saat kita menjalankan fungsi pesanMakan, kita memberikan sebuah callback (dalam hal ini adalah fungsi anonim yang memanggil bayarMakan).

  1. pesanMakan menggunakan setTimeout selama 1,5 detik, lalu menampilkan "πŸ• Makanan dipesan..." di console, dan setelah itu memanggil callback-nya, yaitu bayarMakan.

  2. bayarMakan kemudian dijalankan dan juga menggunakan setTimeout selama 2 detik, menampilkan "πŸ’Έ Makanan dibayar..." di console, lalu menjalankan callback terakhir yang mencetak "Selesai, selamat makan..." ke console.

Jadi, urutan eksekusi adalah:

(1.5 detik) -> πŸ• Makanan dipesan...
(2 detik lagi) -> πŸ’Έ Makanan dibayar...
(Segera setelahnya) -> Selesai, selamat makan...

Seperti yang kalian lihat kode seperti ini sangat sulit dibaca dan dikelola.

Merubah Callback ke Promise

function pesanMakan() {
  return new Promise((resolve, reject) => {
    let statusToko = true;
    setTimeout(() => {
      console.log("πŸ• Makanan dipesan...");
      statusToko ? resolve() : reject("Gagal memesan makanan, toko tutup");
    }, 1500);
  });
}

function bayarMakan() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      let statusQris = true;
      console.log("πŸ’Έ Makanan dibayar...");
      statusQris ? resolve() : reject("QRIS sedang gangguan, mohon maaf");
    }, 2000);
  });
}

pesanMakan()
  .then(() => bayarMakan())
  .then(() => console.log("Selesai, selamat makan."))
  .catch((error) => console.log("Error:", error));

Bisa dibandingkan bahwasannya penggunaan Promise memang lebih mudah dipahami dan lebih rapi dibandingkan dengan callback. Dengan Promise, kita bisa menghindari callback hell dan membuat kode lebih terstruktur serta lebih mudah dibaca.

Apa Itu Fetch API?

Fetch API adalah metode bawaan JavaScript yang digunakan untuk melakukan request HTTP data dari internet (seperti dari server). Fetch API menggunakan Promise, jadi cara kerjanya asynchronous.

Cara Kerja Fetch

  • Mengembalikan Promise yang akan resolve ketika respons diterima.

  • Secara default menggunakan metode GET.

  • Dapat digunakan untuk request POST, PUT, DELETE, dan lainnya.

  • Mendukung JSON, form data, dan lainnya.

Contoh Fetch dengan Metode GET

fetch("https://jsonplaceholder.typicode.com/posts/1")
  .then((response) => response.json()) // Mengubah hasil ke JSON
  .then((data) => {
    console.log("Data:", data);
  })
  .catch((error) => {
    console.log("Terjadi kesalahan:", error.message);
  });

πŸ“Œfetch() akan mengembalikan Promise, yang berarti kita bisa menggunakan .then() untuk menangani hasilnya.
πŸ“Œ response.json() juga mengembalikan Promise, sehingga kita harus menggunakan .then() lagi.

JSONPlaceholder adalah layanan REST API palsu (fake REST API) yang digunakan untuk pengujian dan pengembangan aplikasi. API ini menyediakan data dummy dalam format JSON yang dapat digunakan untuk mencoba operasi GET, POST, PUT, PATCH, dan DELETE tanpa harus membuat backend sendiri.

Hasil:

Data: {
  userId: 1,
  id: 1,
  title: 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit',
  body: 'quia et suscipit\n' +
    'suscipit recusandae consequuntur expedita et cum\n' +
    'reprehenderit molestiae ut ut quas totam\n' +
    'nostrum rerum est autem sunt rem eveniet architecto'
}

Contoh Fetch dengan Metode POST

const options = {
  method: "POST",
  body: JSON.stringify({
    title: "Foo",
    body: "Bar",
    userId: 1,
  }),
  headers: {
    "Content-type": "application/json; charset=UTF-8",
  },
};
fetch("https://jsonplaceholder.typicode.com/posts", options)
  .then((response) => response.json())
  .then((result) => console.log(result))
  .catch((error) => console.log(error));

Hasil:

{ title: 'Foo', body: 'Bar', userId: 1, id: 101 }

Menggunakan Fetch dengan async dan await

async dan await adalah fitur di JavaScript yang digunakan untuk menangani operasi asinkron dengan cara yang lebih mudah dipahami dibandingkan dengan callback atau Promise .then().

Apa itu async?

Kata kunci async digunakan untuk menandai sebuah fungsi agar mengembalikan Promise secara otomatis.

Tanpa async:

function getData() {
  return new Promise(resolve => {
    resolve("Data berhasil diambil");
  })
}

getData()
  .then((result) => console.log(result)) 

// Output: Data berhasil diambil

Fungsi getData mengembalikan Promise, jadi kita harus menggunakan .then() untuk mengambil hasilnya.

Dengan async:

async function getData() {
  return "Data berhasil diambil";
}

getData()
  .then((result) => console.log(result))

// Output: Data berhasil diambil

Perbedaannya:
Saat kita menambahkan async ke fungsi, hasil yang dikembalikan selalu berupa Promise, meskipun kita hanya mengembalikan string biasa.

Apa itu await?

await digunakan di dalam fungsi async untuk menunggu hasil dari sebuah Promise sebelum melanjutkan eksekusi kode berikutnya.

Tanpa await (menggunakan .then()):


function fetchData() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve("Data diterima");
    }, 1500);
  });
}

console.log("Mengambil data...");
fetchData()
    .then(result => console.log(result));
console.log("Menunggu...");

Hasil:

Mengambil data...
Menunggu...
Data diterima

Penjelasan

Urutan Eksekusi:

  1. console.log("πŸ”„ Mengambil data...") langsung dieksekusi.

  2. fetchData() dipanggil, tapi Promise belum selesai (masih menunggu 2 detik).

  3. Karena JavaScript tidak menunggu fetchData(), maka console.log("⏳ Menunggu...") langsung dieksekusi.

  4. Setelah 2 detik, baru console.log(data) dari .then() dijalankan.

Dengan await:

async function getData() {
  console.log("Mengambil data...");  
  let data = await fetchData();
  console.log(data);
  console.log("Selesai...");
}

getData();
console.log("Menunggu...");

Hasil:

Mengambil data...
Menunggu...
Data diterima

Penjelasan

Urutan Eksekusi:

  1. getData() dipanggil.

  2. console.log("πŸ”„ Mengambil data...") dieksekusi.

  3. await fetchData(); membuat getData() menunggu selama 2 detik.

  4. Sementara itu, JavaScript tetap menjalankan kode lain, jadi console.log("⏳ Menunggu...") dieksekusi lebih dulu.

  5. Setelah 2 detik, let data = await fetchData(); selesai dan barulah console.log(data) serta console.log("βœ… Selesai") dieksekusi.

Perbedaan then dan async/await

Mari kita buat analogi menggunakan antrian di restoran untuk memahami perbedaan .then() dan async/await.

1. .then() β†’ Sistem "Ambil Nomor Antrian"

Bayangkan kamu pergi ke restoran dan memesan makanan. Di sini, restoran tidak meminta kamu menunggu di kasir, tapi memberimu nomor antrian.

  1. Kamu memesan makanan πŸ• β†’ (Memanggil fetchData()).

  2. Kasir berkata, "Silakan tunggu, nanti kami panggil nomornya" β†’ (Promise masih pending).

  3. Sementara menunggu makanan, kamu bisa melakukan hal lain, seperti duduk atau bermain HP πŸ“± β†’ (JavaScript lanjut eksekusi kode lain).

  4. Ketika makanan siap, pelayan memanggil nomormu dan memberikannya β†’ (.then() dieksekusi setelah Promise selesai).

Intinya .then():
βœ… Kamu tidak harus menunggu di tempat. Restoran tetap melayani pelanggan lain, dan kamu bisa melakukan aktivitas lain sambil menunggu makanan.

2. async/await β†’ Sistem "Pesan & Tunggu di Tempat"

Sekarang, bayangkan kamu pergi ke restoran cepat saji di mana harus menunggu di kasir sampai pesanan selesai.

  1. Kamu memesan makanan πŸ” β†’ (Memanggil fetchData()).

  2. Kasir berkata, "Silakan tunggu di sini sampai makanan siap" β†’ (await membuatmu menunggu hasilnya).

  3. Kamu tetap di kasir dan tidak melakukan hal lain sampai makanan siap ⏳ β†’ (JavaScript benar-benar menunggu Promise selesai sebelum lanjut ke kode berikutnya).

  4. Ketika makanan siap, kamu langsung menerimanya dan lanjut aktivitas lain β†’ (Baris kode setelah await baru dijalankan setelah Promise selesai).

Intinya async/await:
βœ… Kamu harus menunggu makanan sebelum bisa melakukan hal lain. Restoran tetap melayani pelanggan lain, tapi kamu tidak bisa melakukan hal lain sebelum makananmu selesai.

Kesimpulan dari Antrian Restoran

Fitur.then() (Ambil Nomor Antrian)async/await (Tunggu di Kasir)
Menunggu MakananTidak benar-benar menunggu di kasir, bisa melakukan hal lainHarus menunggu di kasir sampai makanan selesai
Kelancaran SistemLebih efisien, pelanggan bisa tetap melakukan hal lainLebih terstruktur, tapi pelanggan harus menunggu
Urutan EksekusiTidak harus urut, bisa multitaskingHarus urut, menunggu satu per satu
Kapan Menggunakan .then() vs async/await?

πŸš€ Gunakan .then() β†’ Jika ingin tetap menjalankan kode lain tanpa menunggu hasil. Cocok untuk proses paralel seperti loading banyak data secara bersamaan.
πŸš€ Gunakan async/await β†’ Jika urutan eksekusi sangat penting, seperti saat mendapatkan data sebelum menggunakannya.

Contoh Fetch API dengan async/await

async function getData() {
    try {
        let response = await fetch("https://jsonplaceholder.typicode.com/posts/1");
        let data = await response.json();
        console.log("Data:", data);
    } catch (error) {
        console.log("Terjadi kesalahan:", error);
    }
}

getData();

πŸ“Œ await akan menunggu sampai proses fetch() selesai sebelum melanjutkan.
πŸ“Œ Gunakan try...catch untuk menangani error jika terjadi masalah.


Kesimpulan

KonsepPenjelasan
PromiseObjek yang menangani proses asinkron. Bisa resolve (sukses) atau reject (gagal).
.then()Menangani hasil resolve() dalam Promise.
.catch()Menangani error jika reject() dipanggil.
Fetch APIMetode untuk mengambil data dari server dengan fetch(), mengembalikan Promise.
async/awaitCara lebih sederhana untuk menangani Promise dibanding .then().

Dengan memahami Promises & Fetch API, kita bisa menangani data dari internet dengan lebih mudah dan efisien! πŸš€

0
Subscribe to my newsletter

Read articles from Dimas Rizki Mahendra directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Dimas Rizki Mahendra
Dimas Rizki Mahendra

PHP Developer