nextjsfetchasyncMenengah4 mnt baca

Fetch Paralel

Mengambil banyak data sekaligus dengan Promise.all agar tidak antre.

Masalah waterfall: antrean yang tidak perlu

Bayangkan kamu memasak sarapan: mie, telur, dan sayur. Kalau kamu pakai satu kompor dan menunggu mie matang dulu baru mulai menggoreng telur, lalu menunggu telur matang baru merebus sayur, sarapan selesai dalam 15 menit. Padahal kalau tiga kompor dinyalakan bersamaan, semuanya selesai dalam 5 menit. Itulah perbedaan fetch sekuensial vs paralel.

Kenapa ini penting di Next.js? Karena di Server Component sangat mudah menulis await berurutan tanpa sadar, dan setiap await membuat request berikutnya menunggu. Ini disebut waterfall: request-request yang sebenarnya tidak saling bergantung malah antre satu per satu. Total waktu muat menjadi jumlah seluruh request, bukan yang paling lambat saja.

tsx
// app/dashboard/page.ts (contoh pola lambat)
// ❌ Waterfall: posts menunggu user selesai
async function getDashboardBuruk() {
  const user = await fetchUser();
  const posts = await fetchPosts(); // baru mulai setelah user selesai
  const notif = await fetchNotif(); // baru mulai setelah posts selesai
  return { user, posts, notif };
}

Kalau tiap request butuh 1 detik, kode di atas butuh 3 detik. Solusinya: mulai semua promise dulu, await belakangan.

Solusi: mulai bersamaan

tsx
// app/dashboard/page.tsx
// ✅ Paralel: ketiganya jalan bersamaan
import { fetchUser, fetchPosts, fetchNotif } from "@/lib/api";

export default async function Dashboard() {
  const [user, posts, notif] = await Promise.all([
    fetchUser(),
    fetchPosts(),
    fetchNotif(),
  ]);

  return (
    <>
      <h1>Halo, {user.name}</h1>
      <NotifBadge count={notif.length} />
      <PostList posts={posts} />
    </>
  );
}

Dengan Promise.all, tiga request 1 detik selesai dalam sekitar 1 detik total, bukan 3 detik. Ada juga gaya kedua yang setara: simpan promise-nya dulu sebagai variabel, await satu per satu belakangan. Hasilnya sama paralelnya, dan kadang lebih enak dibaca kalau kamu butuh memberi nama tiap hasil.

tsx
// app/laporan/page.tsx
// ✅ Gaya alternatif: mulai dulu, await belakangan
const userPromise = fetchUser();   // mulai sekarang
const postsPromise = fetchPosts(); // mulai sekarang juga

const user = await userPromise;
const posts = await postsPromise;

Kapan tetap sekuensial?

Hanya bila request kedua bergantung pada hasil yang pertama. Contoh klasik: kamu butuh userId dari request pertama untuk mengambil post milik user itu. Kalau datanya tidak saling membutuhkan, tidak ada alasan untuk mengantre.

Satu catatan tambahan: Promise.all gagal total kalau satu request gagal (semuanya melempar error). Kalau kegagalan sebagian masih bisa ditoleransi, misalnya widget cuaca boleh kosong tapi konten utama harus tampil, pakai Promise.allSettled lalu periksa status tiap hasil satu per satu.

Catatan teknis: Waterfall adalah pembunuh performa nomor satu di Server Components. Cara auditnya sederhana: cari await yang ditulis berurutan, tanyakan "apakah request B butuh hasil request A?" Kalau tidak, gabungkan dengan Promise.all. Kebiasaan kecil ini sering memangkas waktu muat halaman sampai separuhnya.

Tantangan

Ukur bedanya

Buat dua versi halaman: fetch 3 API berurutan vs Promise.all (beri delay 1s tiap API). Catat total waktu muat masing-masing di Network tab.