Traffine I/O

Bahasa Indonesia

2022-02-21

Asynchronous JavaScript

Asynchronous JavaScript

JavaScript adalah bahasa pemrograman berurutan tunggal, yang berarti ia hanya dapat menangani satu tugas pada satu waktu. Namun, operasi tertentu seperti pengambilan data dari server, membaca file, atau melakukan kueri ke database dapat memakan waktu yang cukup lama untuk diselesaikan. Di sinilah JavaScript asinkron memainkan peran penting. Ini memungkinkan mesin JavaScript untuk menjalankan tugas lain sambil menunggu operasi-operasi ini selesai.

Dalam pemrograman sinkron, setiap tugas dieksekusi satu per satu. Ini berarti bahwa sebuah tugas harus selesai sebelum tugas berikutnya dimulai. Namun, dalam pemrograman asinkron, tugas-tugas dapat dieksekusi secara bersamaan. Ini berarti tugas-tugas yang memakan waktu lama dapat dimulai dan dibiarkan selesai di latar belakang sementara program utama terus berjalan.

Callback dalam JavaScript

Dalam dunia JavaScript, fungsi berperan penting dalam merancang perilaku aplikasi. Sifat yang serba guna dari fungsi memungkinkan mereka diperlakukan sebagai objek kelas pertama, yang berarti bahwa mereka dapat dilewatkan seperti nilai lain dalam bahasa tersebut. Callback, khususnya, adalah fungsi yang dilewatkan sebagai argumen ke fungsi lain dan diharapkan dieksekusi pada waktu yang tertunda.

Kemampuan untuk meneruskan fungsi sebagai nilai dan menjalankannya nanti membuka peluang yang luas. Callback dapat digunakan untuk memberikan perilaku khusus yang harus dieksekusi setelah suatu operasi selesai, atau ketika kondisi tertentu terpenuhi.

Mengimplementasikan Callback dalam JavaScript

Mari kita pertimbangkan contoh sederhana. Misalkan Anda memiliki sebuah fungsi yang membutuhkan waktu untuk menghitung hasil, seperti pengambilan data dari database. Anda tidak ingin program Anda menunggu dan tidak melakukan apa-apa saat fungsi ini dieksekusi, jadi Anda menggunakan callback.

Berikut adalah contoh kode:

js
function fetchData(callback) {
  // Simulate a delay with setTimeout
  setTimeout(function() {
    let data = 'Hello, world!';
    callback(data);
  }, 2000);
}

function printData(data) {
  console.log(data);
}

// Call fetchData and pass in printData as the callback
fetchData(printData);

Pada contoh ini, fetchData mengambil fungsi callback sebagai argumen. Ia mensimulasikan pengambilan data dengan penundaan menggunakan setTimeout. Ketika data siap, ia memanggil fungsi callback dengan data sebagai argumen. Fungsi printData dilewatkan sebagai callback, sehingga ia dipanggil ketika data siap, dan mencetak data ke konsol.

Masalah dengan Callback Hell

Callback sangat berguna untuk kasus sederhana, tetapi segalanya bisa menjadi rumit ketika Anda mulai menyusun callback dalam callback. Situasi ini sering disebut sebagai "callback hell".

Misalnya, jika Anda perlu mengambil data dari database, kemudian berdasarkan data tersebut mengambil beberapa data lain, dan kemudian berdasarkan data tersebut melakukan sesuatu yang lain, Anda akan berakhir dengan callback yang bertumpuk.

js
fetchData(function(data) {
  fetchMoreData(data, function(moreData) {
    doSomethingWithTheData(moreData, function(result) {
      console.log(result);
    });
  });
});

Kode akan mulai terlihat seperti piramida, dan dapat dengan cepat sulit dibaca dan dipelihara. Ini adalah salah satu masalah utama yang dihadapi oleh Promises dan Async/Await dalam penyelesaiannya.

Promises dalam JavaScript

Sebagai respons terhadap tantangan yang dihadapi oleh callback, terutama "callback hell," Promises diperkenalkan dalam JavaScript. Promises adalah objek yang mewakili penyelesaian atau kegagalan yang akan terjadi pada operasi asinkron. Mereka menyediakan cara yang kuat untuk menangani operasi asinkron dan menghindari penumpukan callback yang dalam.

Keadaan dan Siklus Hidup Promise

Sebuah Promise dapat berada dalam salah satu dari tiga keadaan:

  • Pending (Tertunda): Hasil dari promise belum ditentukan, karena operasi asinkron yang akan menghasilkan hasilnya belum selesai.
  • Fulfilled (Terpenuhi): Operasi asinkron telah selesai, dan promise memiliki nilai hasil.
  • Rejected (Ditolak): Operasi asinkron gagal, dan promise tidak akan pernah terpenuhi. Dalam keadaan ditolak, promise memiliki alasan yang menunjukkan mengapa operasi gagal.
  • Penting untuk dicatat bahwa setelah sebuah promise terpenuhi atau ditolak, keadaannya tidak dapat berubah. Promise dikatakan "settled" jika telah terpenuhi atau ditolak.

Membuat dan Mengonsumsi Promises

Promises dibuat menggunakan konstruktor new Promise. Konstruktor Promise mengambil sebuah fungsi, yang disebut executor, yang memiliki dua argumen: resolve dan reject. Argumen resolve dan reject adalah fungsi yang, ketika dipanggil, menyelesaikan promise. resolve memenuhi promise dengan sebuah nilai, dan reject menolak promise dengan alasan.

Berikut adalah contoh sederhana pembuatan promise:

js
let myFirstPromise = new Promise((resolve, reject) => {
  let condition = true; // this could be the result of some asynchronous operation

  if(condition) {
    resolve('Promise is fulfilled!');
  } else {
    reject('Promise is rejected!');
  }
});

Untuk mengonsumsi sebuah promise, Anda dapat menggunakan metode then-nya. Metode then menerima dua argumen opsional: callback untuk kasus keberhasilan dan callback untuk kasus kegagalan. Callback ini juga dikenal sebagai handler.

Berikut adalah contoh penggunaan promise yang telah kita buat sebelumnya:

js
myFirstPromise
  .then(successMessage => {
    console.log(successMessage);
  })
  .catch(errorMessage => {
    console.error(errorMessage);
  });

Pada contoh ini, jika promise terpenuhi, pesan keberhasilan akan dicetak ke konsol. Jika promise ditolak, pesan kesalahan akan dicetak ke konsol.

Menggabungkan Promises (Chaining Promises)

Salah satu fitur paling kuat dari promises adalah kemampuannya untuk digabungkan bersama. Ini berarti Anda dapat melakukan beberapa operasi asinkron secara berurutan di mana setiap operasi berikutnya dimulai setelah operasi sebelumnya selesai.

Berikut adalah contoh penggabungan promise:

js
fetchData()
  .then(data => {
    console.log(data);
    return fetchMoreData(data);
  })
  .then(moreData => {
    console.log(moreData);
    return doSomethingWithTheData(moreData);
  })
  .then(result => {
    console.log(result);
  })
  .catch(error => {
    console.error(error);
  });

Pada contoh ini, setiap then mengembalikan sebuah promise baru, yang membentuk rantai promise. Jika salah satu promise dalam rantai ditolak, kontrol akan beralih ke metode catch terdekat. Ini membuat penanganan kesalahan dalam rantai promise menjadi sangat sederhana.

Async/Await

Async/Await adalah cara modern untuk menangani operasi asinkron dalam JavaScript. Diperkenalkan dengan ES2017, Async/Await pada dasarnya adalah sintaks gula yang dibangun di atas promises, yang memungkinkan kita bekerja dengan promises dengan cara yang lebih nyaman dan mudah dibaca.

Async/Await membuat kode asinkron terlihat dan berperilaku seperti kode sinkron, yang membuatnya lebih mudah dipahami dan dipahami. Ini adalah alat yang kuat untuk menulis kode JavaScript asinkron yang bersih, ringkas, dan mudah dibaca.

Menggunakan Async/Await dalam JavaScript

Untuk menggunakan Async/Await, Anda memulainya dengan mendefinisikan sebuah fungsi asinkron menggunakan kata kunci async. Di dalam fungsi asinkron, Anda dapat menggunakan kata kunci await sebelum sebuah promise untuk menghentikan eksekusi fungsi asinkron dan menunggu promise tersebut terpenuhi atau ditolak.

Berikut adalah contoh:

js
async function fetchAndDisplayData() {
  try {
    let data = await fetchData();
    console.log(data);

    let moreData = await fetchMoreData(data);
    console.log(moreData);

    let result = await doSomethingWithTheData(moreData);
    console.log(result);
  } catch(error) {
    console.error(error);
  }
}

fetchAndDisplayData();

Pada contoh ini, fetchData, fetchMoreData, dan doSomethingWithTheData adalah fungsi-fungsi yang mengembalikan promise. Kata kunci await sebelum panggilan fungsi ini membuat JavaScript "menunggu" hingga promise diselesaikan, lalu mengembalikan hasilnya. Ini berarti fetchAndDisplayData berperilaku seolah-olah itu adalah fungsi sinkron, meskipun mengandung operasi asinkron.

Penanganan Kesalahan dalam Async/Await

Penanganan kesalahan dalam fungsi asinkron dilakukan menggunakan blok try/catch, seperti dalam kode sinkron. Pada contoh di atas, jika salah satu promise ditolak, eksekusi akan melompat ke blok catch.

Ryusei Kakujo

researchgatelinkedingithub

Focusing on data science for mobility

Bench Press 100kg!