Aliif Arief Homepage

Implementasi Server Sent Events

By Aliif Arief ยท 5 minutes

Table of Contents

Saat sedang mengerjakan proyek untuk salah satu matakuliah ada satu fitur yang harus diimplemntasikan yaitu fitur realtime dashboard monitoring and graphing. Setelah melakukan riset, daripada frontend yang melakukan pooling fetch data dalam interval tertentu yang kurang efektif kami menemukan bahwa ada beberapa cara untuk mengimplementasikan fitur tersebut, salah satunya adalah menggunakan Server Sent Events (SSE).

Apa itu Server Sent Events (SSE)?

Server-Sent Events (SSE) adalah teknologi yang memungkinkan server untuk mengirimkan data ke browser secara asinkron (tanpa polling) dengan cara yang sangat sederhana. Data dikirimkan dalam format text/event-stream dan browser akan menerima data tersebut secara otomatis.

SSE sangat berguna untuk mengirimkan data secara realtime dari server ke browser, seperti notifikasi, update data, dan lain-lain. SSE sangat mudah digunakan dan tidak memerlukan library atau framework tambahan.

SSE memanfaatkan teknologi HTTP, sehingga tidak memerlukan protokol khusus seperti WebSockets. SSE juga mendukung fitur reconnect, sehingga koneksi akan otomatis direstore jika terputus.

Implementasi Server Sent Events

Kali ini kita akan mencoba mengimplementasikan server sent events sederhana dengan menggunakan expressjs sebagai backend/server dan vanilla javascript sebagai frontend/client, kita akan membuat tiruan realtime grafik harga saham yang akan selalu update tanpa perlu melakukan polling apalagi refresh halaman.

Paling tidak ada 3 elemen disini yaitu sumber data saham yang akan selalu post data ke server, server yang akan menerima data dan mengirimkan data ke client dengan event stream, dan client yang akan menerima data dan menampilkan data tersebut.

Bot Data Saham

Tentunya harus ada sumber data masuk untuk menjadikannya sebuah realtime monitoring karena itu kita akan membuat sebuah dummy bot yang pura - puranya akan melakukan fetch post dalam interval tertentu ke server backend, berikut kodenya:

const sendData = async () => {
  //generate random number from 1 to 50
  const random = Math.floor(Math.random() * 50) + 1;
  //unix timestamp now
  const timestamp = Date.now();
  const newdata = { id: timestamp, value: random };
  try {
    // console.log(newdata);
    const response = await fetch("http://localhost:5000/api/saham", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(newdata),
    });
    if (response.ok) {
      console.log("Data sent successfully");
    }
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error("Error:", error.message);
  }
};

setInterval(() => {
  sendData();
}, 5000);

Kode diatas akan mengirimkan data saham ke server backend dalam interval 5 detik, data yang dikirimkan adalah data random dari 1 sampai 50.

Backend

Setelah bot melakukan posting data maka selanjutnya server/backend akan menyimpannya kali ini kita simpan ke dalam array kosong saja lalu tiap ada update data dari bot maka server akan mengirimkan data tersebut ke client dengan sse, berikut kodenya:

import express from "express";
import cors from "cors";

const app = express();

app.use(express.json());
app.use(
  cors({
    origin: "http://127.0.0.1:5500",
  })
);

//untuk menyimpan koneksi client sse yang aktif
const clients = [];
// database array saham sederhana
const saham = [];

app.post("/api/saham", (req, res) => {
  const { id, value } = req.body;
  saham.push({ id, value });
  //kirim pembaruan ke client
  sendSSEUpdate(saham);
  res.json({ id, value });
});

//server sent event endpoint
app.get("/api/saham", (req, res) => {
  //set header untuk server sent event
  res.setHeader("Content-Type", "text/event-stream");
  res.setHeader("Cache-Control", "no-cache");
  res.setHeader("Connection", "keep-alive");

  //ketika client terhubung, tambahkan res ke daftar client
  const client = {
    id: Date.now(),
    res,
  };
  clients.push(client);

  //ketika client disconnect, hapus client dari daftar
  req.on("close", () => {
    console.log(`${client.id} Connection closed`);
    clients.splice(clients.indexOf(client), 1);
    res.end();
  });
});

//kirim pembaruan ke client
function sendSSEUpdate(data) {
  clients.forEach((client) => {
    //kirim data ke client
    const responseData = `data: ${JSON.stringify(data)}\n\n`;
    client.res.write(responseData);
  });
}

app.listen(5000, () => {
  console.log("Server is running on port 5000");
});

Kode diatas akan membuat server backend yang akan menerima data dari bot dan mengirimkan data tersebut ke client dengan metode sse, server backend akan berjalan di port 5000.

Frontend

Terakhir kita akan membuat frontend/client yang akan menerima data dari via event stream dan menampilkan data tersebut dalam bentuk grafik dengan menggunakan chart.js, berikut kodenya:

<!DOCTYPE html>
<html lang="id">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Server Sent Events</title>
  </head>
  <body>
    <h1>Grafik Harga Sama $ALAM</h1>
    <div id="app">
      <canvas id="myChart" width="400" height="400"> </canvas>
    </div>
  </body>
  <!-- chart.js -->
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

  <!-- SSE -->
  <script>
    const ctx = document.getElementById("myChart").getContext("2d");
    const myChart = new Chart(ctx, {
      type: "line",
      data: {
        labels: [],
        datasets: [
          {
            label: "Harga $ALAM",
            data: [],
            backgroundColor: "rgba(255, 99, 132, 0.2)",
            borderColor: "rgba(255, 99, 132, 1)",
            borderWidth: 1,
          },
        ],
      },
      options: {
        responsive: true,
        scales: {
          y: {
            beginAtZero: true,
          },
        },
      },
    });

    const eventSource = new EventSource("http://localhost:5000/api/saham");
    eventSource.onmessage = (event) => {
      const data = JSON.parse(event.data);
      //console.log(data);
      myChart.data.labels = data.map((d) => d.id);
      myChart.data.datasets[0].data = data.map((d) => d.value);
      myChart.update();
    };

    eventSource.onerror = (error) => {
      console.error("EventSource failed:", error);
      eventSource.close();
    };
  </script>
</html>

Kode diatas akan membuat grafik harga saham $ALAM yang akan selalu update data dalam bentuk grafik, data yang diterima dari server backend akan diupdate dalam grafik tersebut.

Kesimpulan

Daripada menggunakan polling atau refresh halaman berkala, Server-Sent Events (SSE) memungkinkan kita untuk mengirimkan data secara realtime dari server ke browser dengan cara yang lebih efektif dan efisien serta dapat menghemat bandwidth baik dari sisi server maupun client. untuk realtime monitoring seringnya lebih tepat menggunakan SSE daripada WebSockets karena tidak memerlukan komunikasi full-duplex berbeda halnya misal realtime chat, game, dll. yang memerlukan komunikasi full-duplex/dua arah(websockets).

Semoga bermanfaat tntuk full source code bisa dilihat di Repositori ini, jika ada error atau pertanyaan silahkan tulis di kolom komentar.

----

โœ๏ธ at 07:47 on April 27, 2024
๐Ÿ†• at 20:57 on April 29, 2024

ccTv dan ccTuhan