Ketika mencari jawaban tentang apa itu callback javascript, callback function javascript, atau promise all di mesin pencari, kebanyakan orang sebenarnya sedang menghadapi satu masalah yang sama: kode JavaScript tidak berjalan sesuai urutan yang mereka bayangkan. Sebuah fungsi selesai lebih dulu, padahal hasilnya baru dibutuhkan setelah proses lain kelar. Artikel ini menjawab langsung kebutuhan tersebut, mulai dari pengertian callback, alasan munculnya promise, sampai cara memakai Promise.all untuk menjalankan banyak tugas asynchronous secara bersamaan.
JavaScript berjalan pada satu thread, tetapi banyak pekerjaan di dalamnya bersifat asynchronous: mengambil data dari API, membaca file, atau menunggu timer. Agar antarmuka tidak membeku, pekerjaan seperti itu tidak ditunggu secara langsung. Di sinilah callback dan promise berperan sebagai cara mengatur kapan sebuah kode boleh dijalankan setelah pekerjaan lain selesai.
Apa Itu Callback dalam JavaScript?
Callback adalah fungsi yang dikirim sebagai argumen ke fungsi lain, lalu dipanggil di dalam fungsi tersebut pada waktu yang ditentukan. Dengan kata lain, callback adalah cara menitipkan instruksi: “setelah tugas ini selesai, jalankan fungsi berikut”. Pola ini sudah lama menjadi fondasi asynchronous JavaScript, terutama sebelum promise dan async/await populer.
Callback sebagai Fungsi yang Dikirim sebagai Argumen
Kunci memahami callback adalah posisinya sebagai nilai. Di JavaScript, fungsi adalah objek, sehingga bisa disimpan dalam variabel, dikembalikan dari fungsi lain, dan dikirim sebagai parameter. Ketika sebuah fungsi menerima parameter berupa fungsi, fungsi itulah yang disebut callback.
function sapa(nama, callback) {
const pesan = `Halo, ${nama}`;
callback(pesan);
}
sapa('Budi', function (hasil) {
console.log(hasil);
});
Pada contoh di atas, fungsi anonim yang mencetak hasil adalah callback. Fungsi sapa tidak tahu apa yang akan dilakukan callback; ia hanya memanggilnya setelah pesan siap.
Contoh Callback Sederhana
Callback paling mudah dikenali pada fungsi bawaan seperti setTimeout dan addEventListener. Keduanya menerima fungsi yang baru dijalankan ketika waktu habis atau ketika sebuah peristiwa terjadi.
setTimeout(function () {
console.log('Muncul setelah dua detik');
}, 2000);
document.querySelector('#tombol').addEventListener('click', function () {
console.log('Tombol diklik');
});
Pola yang sama dipakai saat mengambil data. Callback memastikan kode pengolah data hanya berjalan setelah respons tersedia, bukan sebelum permintaan dikirim.
Callback Hell dan Masalahnya
Masalah muncul ketika banyak operasi asynchronous harus berurutan. Callback disusun di dalam callback, lalu di dalam callback lagi, sehingga kode menjorok ke kanan dan sulit dibaca. Kondisi ini dikenal sebagai callback hell.
ambilPengguna(function (pengguna) {
ambilPesanan(pengguna.id, function (pesanan) {
ambilDetail(pesanan.id, function (detail) {
console.log(detail);
});
});
});
Selain sulit dibaca, penanganan error menjadi berulang dan rawan terlewat. Setiap level perlu memeriksa error sendiri, dan satu kesalahan kecil dapat membuat alur sulit dilacak. Untuk memperkuat dasar sebelum masuk lebih jauh, panduan belajar JavaScript untuk pemula membahas fungsi, objek, dan alur eksekusi yang menjadi prasyarat memahami pola ini.
Dari Callback ke Promise
Promise adalah objek yang mewakili hasil akhir dari sebuah operasi asynchronous. Alih-alih menitipkan callback ke dalam fungsi, promise mengembalikan objek yang bisa ditangani dengan .then() dan .catch(). Perubahan ini membuat alur kode lebih datar dan penanganan error lebih terpusat.
Tiga Status Promise
Sebuah promise selalu berada pada salah satu dari tiga status berikut.
- Pending, yaitu status awal ketika operasi belum selesai.
- Fulfilled, yaitu status ketika operasi berhasil dan menghasilkan nilai.
- Rejected, yaitu status ketika operasi gagal dan membawa alasan kegagalan.
Status hanya berubah satu kali. Setelah fulfilled atau rejected, promise dianggap selesai dan tidak bisa berubah lagi.
then, catch, dan finally
Metode .then() menerima fungsi yang dijalankan saat promise fulfilled, sedangkan .catch() menangani rejection. Metode .finally() dijalankan pada kedua kondisi dan berguna untuk membersihkan sumber daya.
fetch('https://api.example.com/pengguna')
.then((respons) => respons.json())
.then((data) => console.log(data))
.catch((error) => console.error('Gagal:', error))
.finally(() => console.log('Selesai'));
Rantai seperti ini lebih mudah dibaca daripada callback bersarang. Jika Anda ingin melihat bagaimana sintaks modern seperti arrow function dan modul dipakai bersama promise, artikel fitur ES6+ dalam JavaScript menjelaskan perubahan sintaks yang relevan.
Memahami Promise.all
Promise.all adalah metode statis yang menerima array promise dan mengembalikan satu promise baru. Promise baru itu fulfilled ketika semua promise di dalam array fulfilled, dan rejected begitu ada satu promise yang rejected. Hasilnya berupa array nilai dengan urutan yang sama seperti urutan promise aslinya.
Cara Kerja Promise.all
Karena semua promise dijalankan secara bersamaan, total waktu tunggu mengikuti promise yang paling lambat, bukan jumlah seluruh waktu masing-masing. Inilah alasan Promise.all sangat berguna ketika beberapa permintaan data tidak saling bergantung dan bisa dilakukan paralel.
Contoh Promise.all
const pengguna = fetch('https://api.example.com/pengguna').then((r) => r.json());
const pesanan = fetch('https://api.example.com/pesanan').then((r) => r.json());
const produk = fetch('https://api.example.com/produk').then((r) => r.json());
Promise.all([pengguna, pesanan, produk])
.then(([dataPengguna, dataPesanan, dataProduk]) => {
console.log(dataPengguna, dataPesanan, dataProduk);
})
.catch((error) => console.error('Salah satu permintaan gagal:', error));
Perhatikan bahwa ketiga permintaan mulai berjalan hampir bersamaan. Jika dijalankan berurutan dengan await, total waktunya menjadi jumlah dari ketiga permintaan. Dengan Promise.all, total waktunya mendekati permintaan terlama.
Kapan Promise.all Tepat Digunakan
Promise.all cocok ketika semua hasil dibutuhkan dan kegagalan salah satu bagian memang harus menggagalkan keseluruhan proses. Contohnya memuat profil, daftar pesanan, dan ringkasan keranjang sebelum menampilkan halaman akun. Jika salah satu data gagal diambil, halaman memang tidak bisa ditampilkan dengan lengkap.
Promise.all dan Promise.allSettled
Jika ingin tetap mendapatkan hasil dari promise yang berhasil meskipun ada yang gagal, gunakan Promise.allSettled(). Metode ini menunggu semua promise selesai dan mengembalikan status masing-masing, baik fulfilled maupun rejected. Pilihan antara keduanya bergantung pada apakah kegagalan satu bagian boleh diabaikan atau tidak.
Praktik Terbaik Menulis Kode Asynchronous
Beberapa kebiasaan berikut membantu kode asynchronous tetap mudah dirawat.
- Gunakan
async/awaituntuk alur yang berurutan karena lebih mudah dibaca daripada rantai.then(). - Simpan Promise.all untuk pekerjaan yang benar-benar independen agar tidak menambah beban server secara berlebihan.
- Selalu tangani error dengan
.catch()atautry...catch, termasuk saat memakai Promise.all. - Batasi jumlah permintaan paralel ketika berhadapan dengan API yang memiliki kuota.
- Hindari mencampur callback gaya lama dan promise dalam satu alur tanpa alasan jelas.
Dokumentasi dasar-dasar JavaScript modern dari MDN menjadi rujukan yang tepat untuk memperdalam perilaku promise, event loop, dan fitur bahasa lain secara resmi.
Kesimpulan
Callback adalah fungsi yang dikirim sebagai argumen dan dipanggil setelah tugas tertentu selesai. Pola ini sederhana, tetapi menjadi sulit dirawat ketika operasi asynchronous bertumpuk. Promise hadir untuk merapikan alur tersebut melalui status pending, fulfilled, dan rejected, serta metode .then(), .catch(), dan .finally(). Promise.all melengkapi keduanya dengan kemampuan menjalankan banyak promise secara paralel dan menunggu semuanya selesai. Dengan memahami perbedaan callback, promise, dan Promise.all, Anda dapat memilih pendekatan yang paling tepat untuk setiap kebutuhan dan menulis kode asynchronous yang lebih rapi, aman, dan mudah dipelajari.
Foto sampul oleh Mohammad Rahmani di Unsplash.
