Lewati ke konten utama
menjadi.dev
Chapter 3.2 JavaScript Menengah

Callback: Fungsi dalam Fungsi

Konsep callback dan callback hell

Tujuan Pembelajaran

  • Memahami konsep callback function
  • Mengerti masalah callback hell dan solusinya

Analogi

Diagram

      Callback = Surat Pengingat:

Kamu: 'Mas, kalau nasi gorengnya jadi, antar ke meja 5 ya.'
Pelayan: 'Oke, saya ingat.'

(Nasi goreng jadi)
Pelayan: 'Ini untuk meja 5!' (callback dipanggil)
    

Callback = 'panggil saya kalau sudah selesai'

Penjelasan Konsep

Bayangkan kamu berada di tengah keramaian konser musik. Ada ribuan orang, dan kamu ingin memberikan sesuatu ke orang-orang tertentu. Kalau kamu teriak “Halo semua!”, semua orang akan menoleh — itu adalah selektor universal. Tapi kalau kamu bilang “Kaos merah maju!”, cuma yang pakai kaos merah yang maju — itu adalah selektor class.

Kalau kamu sebut nama “Budi!”, hanya Budi yang merespons — itu adalah selektor ID. CSS bekerja dengan cara yang sama: selektor menentukan elemen mana yang akan menerima styling.

Selektor Dasar

Selektor Elemen (Type Selector)

Memilih semua elemen dengan tag tertentu. h1 { color: blue; } → Semua h1 jadi biru. p { font-size: 14px; } → Semua paragraf jadi 14px. Paling umum digunakan untuk styling global dan reset dasar.

Selektor Class (.)

Memilih elemen dengan class tertentu.

Satu elemen bisa punya banyak class, dan banyak elemen bisa punya class yang sama. Inilah yang membuat class sangat fleksibel dan menjadi selektor yang paling sering digunakan. .btn { padding: 10px; } → Semua elemen dengan class=“btn” .btn.primary { background: blue; } → Elemen dengan class=“btn primary” (dua class sekaligus!)

Selektor ID (#)

Memilih elemen dengan ID tertentu. ID harus UNIK di satu halaman — tidak boleh ada dua elemen dengan ID sama.

Karena unik, ID punya specificity tertinggi di antara selektor dasar. #header { height: 80px; } → Elemen dengan id=“header”

4. Selektor Descendant (Spasi) — Memilih elemen yang berada di dalam elemen lain,

Tidak peduli seberapa dalam. nav a { color: red; } → Semua <a> yang ada di dalam <nav> .card p { font-size: 12px; } → Semua <p> di dalam elemen dengan class=“card”

5. Selektor Child Direct (>) — Memilih elemen yang LANGSUNG menjadi anak (bukan cucu atau lebih dalam).

ul > li { list-style: square; } → Hanya <li> yang langsung di dalam <ul>

6. Selektor Adjacent Sibling (+) — Memilih elemen yang bersebelahan langsung setelah elemen tertentu.

h2 + p { margin-top: 0; } → Paragraf yang langsung setelah h2

Pseudo-class: Selektor Keadaan

Pseudo-class memilih elemen berdasarkan keadaan (state) tertentu:

  • :hover — Saat mouse berada di atas elemen
  • :focus — Saat elemen sedang difokus (klik atau tab)
  • :active — Saat elemen sedang di-klik (ditahan)
  • :first-child — Elemen pertama di antara saudaranya
  • :last-child — Elemen terakhir
  • :nth-child(n) — Elemen ke-n
  • :not(selector) — Elemen yang TIDAK cocok dengan selektor

Pseudo-element: Bagian Elemen

Pseudo-element men-target bagian spesifik dari elemen:

  • ::before — Menambahkan konten sebelum elemen
  • ::after — Menambahkan konten setelah elemen
  • ::first-line — Baris pertama teks
  • ::first-letter — Huruf pertama teks

Specificity: Siapa yang Menang?

Ketika dua aturan CSS bertabrakan, specificity menentukan mana yang menang:

  1. Inline style (1000 poin) — paling kuat
  2. ID selector (100 poin) — #header
  3. Class/pseudo-class/attribute (10 poin) — .btn, :hover, [type="text"]
  4. Elemen/pseudo-element (1 poin) — div, ::before

Specificity dihitung dengan sistem ini.

Contoh: #nav .menu a = 100 + 10 + 1 = 111 poin.

Aturan Cascade

Kalau specificity sama,

Aturan yang ditulis TERAKHIR yang menang.

Aturan !important

Menimpa semua specificity.

Gunakan dengan sangat hemat!

Contoh Kode

javascript
// CALLBACK HELL
getUser(1, (user) => {
  getOrders(user.id, (orders) => {
    getProducts(orders[0].id, (products) => {
      getReviews(products[0].id, (reviews) => {
        console.log(reviews); // Menjorok terus...
      });
    });
  });
});

// SOLUSI: REFACTOR KE FUNGSI TERPISAH
function handleUser(user) {
  getOrders(user.id, handleOrders, handleError);
}
function handleOrders(orders) {
  getProducts(orders[0].id, handleProducts, handleError);
}
function handleProducts(products) {
  getReviews(products[0].id, handleReviews, handleError);
}
function handleReviews(reviews) {
  console.log(reviews);
}
function handleError(err) {
  console.error(err);
}

getUser(1, handleUser, handleError); // Lebih rapi!

Penjelasan Kode

Baris 1-9: Callback hell — nested callback. Baris 12-27: Solusi — pisahkan menjadi fungsi named.

Prompt AI

Jelaskan kenapa callback hell disebut 'pyramid of doom'. Apa kelemahannya?

Pertanyaan Reflektif

Cari kode callback bersarang di proyekmu. Berapa level nesting terdalam? Coba refactor.