Episode ini membangun live dashboard: kebutuhan update frekuensi tinggi, pola streaming dan delta update, integrasi Chart.js dan D3, serta optimasi rendering dengan throttle dan Web Worker.

Dashboard monitoring adalah wajah aplikasi real-time yang paling terlihat: grafik bergerak, angka berubah, peringatan muncul. Tapi dashboard yang buruk adalah dosa — grafik yang dirender 60 kali per detik membekukan browser, dan angka yang telat adalah kebohongan.
Episode 22 membahas live dashboard & data streaming: menerima update frekuensi tinggi, memilih pola streaming yang tepat, mengintegrasikan chart library, dan menjaga browser tetap mulus di tengah ribuan titik data.
Tidak semua dashboard sama. Pahami dulu karakteristiknya:
Trading chart : puluhan update per detik
Monitoring : satu hingga beberapa per detik
Log viewer : burst, lalu hening
Analytics : satu per menit sudah cukupBeban menentukan arsitektur: trading butuh batching dan sampling, log viewer butuh antrean yang tidak menumpuk. Dashboard yang memaksa semua data ke semua klien akan runtuh sendiri.
Ada dua cara mengirim update: snapshot penuh atau delta.
const snapshot = {
type: "snapshot",
data: semuaPoin,
};
const delta = {
type: "delta",
data: { harga: 1023, pada: Date.now() },
};snapshot dikirim sekali saat klien terhubung — berisi state penuh. Setelah itu hanya delta: perubahan kecil yang mengganti nilai. Pola ini menghemat bandwidth berlipat dibanding mengirim seluruh dataset setiap update.
Snapshot yang besar dipecah menjadi beberapa frame agar tidak memblokir event loop dan socket.
function kirimChunk(socket, data) {
const ukuran = 1000;
for (let i = 0; i < data.length; i += ukuran) {
socket.emit("snapshot:chunk", data.slice(i, i + ukuran));
}
socket.emit("snapshot:selesai");
}data.slice(i, i + ukuran) mengirim 1000 titik per frame. Klien menunggu event snapshot:selesai lalu merender seluruh data sekaligus.
Chart.js cocok untuk dashboard yang update beberapa kali per detik.
const chart = new Chart(ctx, {
type: "line",
data: { labels: [], datasets: [{ data: [] }] },
});
ws.onmessage = (event) => {
const d = JSON.parse(event.data);
chart.data.labels.push(d.label);
chart.data.datasets[0].data.push(d.nilai);
if (chart.data.labels.length > 60) {
chart.data.labels.shift();
chart.data.datasets[0].data.shift();
}
chart.update();
};chart.data.datasets[0].data.push(d.nilai) menambah titik baru, shift() membuang titik tertua sehingga hanya 60 titik terakhir dirender. Ini contoh windowing: tampilkan jendela bergulir, bukan seluruh riwayat.
D3.js lebih fleksibel untuk visualisasi kompleks dan dataset besar. Kuncinya: jangan menyerahkan render penuh ke D3 setiap update — gunakan pattern update yang hanya memindahkan elemen yang berubah.
Browser merender sekitar 60 frame per detik. Update data yang datang 200 kali per detik harus di-throttle.
let terakhir = 0;
ws.onmessage = (event) => {
const kini = performance.now();
if (kini - terakhir < 100) return;
terakhir = kini;
prosesUpdate(JSON.parse(event.data));
};kini - terakhir < 100 membatasi pemrosesan visual maksimal 10 kali per detik. Data tetap diterima penuh, tapi render dipertahankan pada kecepatan yang manusiawi untuk dilihat.
Agregasi dan transformasi data berat sebaiknya tidak dijalankan di thread utama.
const worker = new Worker("aggregator.js");
ws.onmessage = (event) => {
worker.postMessage(event.data);
};
worker.onmessage = (event) => {
renderChart(event.data);
};worker.postMessage(event.data) mengirim data mentah ke worker, dan hasil agregasi dikembalikan ke thread utama hanya untuk dirender. Thread utama tetap sibuk merender UI, bukan menghitung.
Episode 22 membuat dashboard yang jujur dan mulus: pola delta yang hemat, snapshot yang ter-chunk, windowing yang menjaga memori, dan throttling yang melindungi browser.
Inti yang harus dibawa pulang:
Di episode 23 berikutnya kita membangun multiplayer game basics: server otoritatif, sinkronisasi state game, input handling, mitigasi latensi, dan optimasi khusus game.