Episode ini membahas cara aplikasi Svelte mengambil data: fetch dan async/await, reactive data loading dengan error handling, load functions SvelteKit untuk data sisi server, serta pola caching sederhana dan manajemen request state.

Hampir semua aplikasi nyata menampilkan data yang tidak ada di dalam kode: daftar pengguna, harga saham, artikel berita. Data itu datang dari server lewat HTTP, dan mengelola proses ini dengan benar adalah keterampilan inti pengembangan web. Episode 8 membuka fase ketiga series: workloads, konfigurasi, dan manajemen data.
Ada dua tempat untuk mengambil data di ekosistem Svelte. Di dalam komponen dengan fetch dan async/await biasa, atau di sisi server dengan load functions SvelteKit yang berjalan sebelum halaman dirender. Masing-masing punya kekuatan sendiri, dan kalian akan belajar memilih yang tepat untuk kebutuhan.
Di episode ini kalian akan mempelajari fetching dengan fetch, reactive data loading dan error handling, load functions di SvelteKit, serta pola caching sederhana dan request state. Setelah selesai, kalian bisa membangun halaman yang memuat data dengan rapi dan tangguh terhadap error.
Fetch di dalam komponen biasanya dipasang di onMount atau langsung di top-level $state. Pola paling sederhana menggunakan async/await:
<script>
let data = $state([])
let error = $state(null)
async function muat() {
try {
const res = await fetch("/api/items")
data = await res.json()
} catch (err) {
error = err
}
}
muat()
</script>fetch("/api/items") mengirim request GET. await res.json() menunggu response dan mengubahnya menjadi object. Membungkus dalam try/catch menangkap error jaringan dan menyimpannya ke state error untuk ditampilkan.
Menjalankan async function saat inisialisasi adalah pola umum. Untuk memastikan fungsi berjalan sekali saja, panggil langsung di top-level atau lewat onMount:
<script>
let data = $state([])
let memuat = $state(true)
onMount(async () => {
const res = await fetch("/api/items")
data = await res.json()
memuat = false
})
</script>
{#if memuat}
<p>Memuat data...</p>
{:else}
<ul>
{#each data as item}
<li>{item.nama}</li>
{/each}
</ul>
{/if}onMount(async () => ...) menjalankan fetch setelah komponen masuk DOM. State memuat memberi tahu pengguna bahwa data sedang diproses. Ini adalah request state paling dasar: memuat, sukses, dan gagal.
Aplikasi yang baik tidak menampilkan layar kosong saat menunggu atau gagal. Representasikan status dengan state eksplisit:
<script>
let status = $state("idle")
let data = $state([])
async function muat() {
status = "loading"
try {
const res = await fetch("/api/items")
if (!res.ok) throw new Error(`HTTP ${res.status}`)
data = await res.json()
status = "success"
} catch (err) {
status = "error"
}
}
</script>
{#if status === "loading"}
<p>Memuat...</p>
{:else if status === "error"}
<p>Terjadi kesalahan saat memuat data</p>
<button onclick={muat}>Coba lagi</button>
{:else if status === "success"}
<p>{data.length} item dimuat</p>
{/if}res.ok bernilai false untuk status 4xx dan 5xx — tanpa ini, res.json() tetap dipanggil meski response gagal. Pola status idle, loading, success, error adalah fondasi request state yang bisa kalian pakai di seluruh aplikasi.
SvelteKit menyediakan cara yang lebih baik: load functions. Fungsi ini berjalan di server (saat SSR) atau di klien (saat navigasi), sebelum halaman dirender. Data yang dikembalikan tersedia sebagai props di komponen halaman. Keuntungannya: data tidak pernah diekspos sebagai request browser, dan fetching bisa berjalan paralel dengan pembentukan HTML.
Load function diekspor dari file +page.js atau +page.server.js. Yang kedua berjalan hanya di server dan dapat mengakses database atau secret:
export async function load({ fetch }) {
const res = await fetch("/api/items")
if (!res.ok) throw new Error("Gagal memuat item")
return {
items: await res.json(),
}
}export async function load({ fetch }) adalah load function. Objek yang dikembalikan menjadi data di komponen halaman. fetch yang diterima adalah fetch khusus SvelteKit — ia meneruskan cookie dan bekerja di server maupun klien.
Komponen halaman menerima hasil load function sebagai prop data. Semua logika fetching tersembunyi di file +page.js; komponen hanya fokus merender daftar data.items. Ini pemisahan tanggung jawab yang bersih — dan kalian akan menggunakannya terus di episode routing berikutnya.
Untuk data yang jarang berubah, hindari fetch berulang dengan cache sederhana:
import { writable } from "svelte/store"
const cache = new Map()
export const item = writable(null)
export async function ambilItem(id) {
if (cache.has(id)) {
item.set(cache.get(id))
return
}
const res = await fetch(`/api/items/${id}`)
const data = await res.json()
cache.set(id, data)
item.set(data)
}cache.has(id) memeriksa apakah data sudah pernah diambil. Jika ya, kembalikan tanpa request; jika tidak, simpan hasilnya ke Map setelah fetch. Store item memberi tahu komponen tentang data terbaru. Pola ini disebut cache-aside dan menjadi dasar library data fetching yang lebih besar.
Inti yang harus dibawa pulang:
fetch dengan async/await dan try/catch adalah pola dasar pengambilan data di komponen.res.ok sebelum membaca body — response 4xx bukan exception otomatis.idle, loading, success, error agar UI selalu informatif.$props.+page.server.js dipakai saat kalian butuh akses ke secret atau database.Di episode 9 selanjutnya kita akan membahas routing dan navigasi — routing berbasis filesystem SvelteKit, dynamic dan nested routes, navigasi dengan <a> dan goto(), serta route parameters, query parameters, dan preload. Load functions yang kalian pelajari hari ini adalah jantung sistem routing itu.