Coba kamu pesen makanan di restoran terus bilang ke pelayan: "Kalo udah jadi, panggil aku ya, aku ada di meja sebelah." Kamu gak nungguin di dapur — kamu kasih instruksi (panggil aku), terus pergi ngerjain hal lain. Pelayan bakal eksekusi instruksi itu nanti pas kondisi tercapai. Itu callback dalam JavaScript: fungsi yang kamu kasih ke fungsi lain, akan dipanggil "nanti" pas waktunya. Jantung dari pemrograman asynchronous — JavaScript gak block, tapi tetep tau cara reaksi pas event terjadi.
🤔 Era pre-Promise. Sebelum 2015, semua kode async pake callback. Hasilnya: "callback hell" — pyramid kode yang nested 10 level dalam, susah baca. Promise (2015) + async/await (2017) ngegantiin pola lama, tapi callback tetep jadi fondasi yang harus dipahami — semua framework modern dasarnya callback yang dibungkus abstraksi yang lebih nyaman.
function prosesData(data, callback) {
const hasil = data.toUpperCase();
callback(hasil);
}
prosesData("halo", function(result) {
console.log(result); // "HALO"
});
Callback sangat umum di JavaScript:
setTimeout(callback, ms)— jalankan setelah delayarray.forEach(callback)— jalankan untuk setiap elemenbutton.addEventListener("click", callback)— jalankan saat diklik
Callback Hell — masalah ketika callback bersarang terlalu dalam:
ambilUser(id, function(user) {
ambilPesanan(user, function(pesanan) {
ambilDetail(pesanan, function(detail) {
// callback hell! Sulit dibaca dan di-debug
});
});
});
Solusinya: gunakan Promise atau async/await (pelajaran selanjutnya).
🎭 Analogi sehari-hari
Callback = titip pesan ke teman: "kalau dia datang, bilang aku tunggu di kafe." Kamu tidak diam menunggu — kamu pergi, dan teman yang menjalankan pesan nanti pas kondisi tercapai.
setTimeout = pesan dengan delay. Click handler = pesan untuk dijalankan kapan pun user klik. JS tidak nunggu — dia kasih pesan ke browser, lanjut kerja, browser yang panggil pas waktunya.
⚠️ Jebakan yang sering ditemui
- Callback hell (nested deep) = kode susah baca + susah debug. Pakai Promise/async-await.
- Lupa
returndi chain = chain putus.thentanpa return = next then dapat undefined. - Sync vs async callback bingung urutan.
arr.forEach(cb)sync (selesai semua dulu),setTimeout(cb)async (tunda). thisdi callback hilang — terutama difunction() {...}callback. Pakai arrow() => {...}atau.bind(this).- Error di callback async tidak ke-catch try/catch luar. Async callback error = unhandled promise rejection.
- Callback dipanggil 0/1/banyak kali.
setTimeout1x,setIntervalbanyak,addEventListener0+. Pikirkan lifecycle saat passing closure. - Callback signature tidak konsisten. Node-style:
(err, data) => {}. Promise-style:(data) => {}. Salah baca = bug.
TL;DR: Callback = function yang dikasih ke function lain, dipanggil "nanti" pas waktunya. Jantung pemrograman async JavaScript. Pattern umum di setTimeout, forEach, addEventListener. Nested terlalu dalam = "callback hell" — solusi modern: Promise + async/await. Awas this putus di callback (pakai arrow), error async tidak ke-catch try/catch luar, dan callback dipanggil 0/1/banyak kali tergantung jenis API.