ลองเล่น server-sent events ทางเลือกใหม่ของการทำ Realtime Web Application

Phawin
odds.team
Published in
2 min readSep 20, 2019
Photo by Carlos Muza on Unsplash

Realtime Web Application คือเว็บที่ต้องแสดงผลทันทีทันใจเช่น ราคาหุ้น /ผลบอล / แชท

ก่อนหน้านี้เวลาจะทำ Realtime Web Application เนี่ยในหัวผมมีอยู่ 2 options คือ

  1. Polling

2. Websocket

แต่วันนี้ผมจะพามารู้จักกับ server-sent events เป็น Technology ตัวนึงที่ใน Document บอกไว้ว่า

Developing a web application that uses server-sent events is easier than with websockets. You’ll need a bit of code on the server to stream events to the front-end, but the client side code works almost identically to handling any other event.

TLDR: ง่ายและเขียนน้อยกว่า Websocket

เดี๋ยวผมจะจำลอง Application ง่ายๆที่รับ Request เข้ามาเป็น Message แล้วให้แสดงผลออกหน้าจอแบบ Realtime โดยจะใช้ Backend เป็น ExpressJS / Frontend เป็น HTML + Javascript ธรรมดาๆ

อ่ะมาเริ่มที่เขียน Backend กันก่อนเลย

const EventEmitter = require("eventemitter3")
const emitter = new EventEmitter()
const express = require("express")
const cors = require("cors")
var app = express()
const subscribe = (req, res) => {
res.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive"
})
const onMessage = data => {
res.write(`data: ${JSON.stringify(data)}\n\n`)
}
emitter.on("message", onMessage)req.on("close", function() {
emitter.removeListener("message", onMessage)
})
}
const publish = (req, res) => {
emitter.emit("message", req.body)
res.json({ message: "success" })
}
app.use(cors())
app.use(express.json())
app.post("/", publish)
app.get("/", subscribe)
app.listen(3000, () => {})

ใช้ lib eventemitter3 ช่วยทำ EventEmitter อย่าลืมลงกันก่อนนะ

ตรง `res.write(`data: ${JSON.stringify(data)}\n\n`)` นี่สำคัญมากๆถ้าไม่ได้ส่งออกไปด้วย data ข้อมูลจะไม่เข้าที่ฝั่ง Frontend

โดยจะเขียนให้ Post ข้อความด้วย HTTP Post มาที่ / และฝั่งคนที่จะดู Message ก็ Subscribe ที่ url เดียวกัน

ทีนี้มาเขียนหน้าเว็บของเรากันบ้าง

<html>
<body>
<div id="messages">
</div>
<script>
let source = new EventSource('http://localhost:3000')
source.onmessage = event => {
data = JSON.parse(event.data)
document.getElementById('messages').insertAdjacentHTML('beforeend', `<p>${data.message}</p>`)
}
</script>
</body>
</html>

สร้าง Source ขึ้นมาที่ URL http://localhost:3000 แล้วให้แสดงผล message ออกทางหน้าจอ

เพียงเท่านี้เราก็จะได้ Realtime web application ที่แสดงผลข้อความตามที่มีการส่ง Request เข้ามาเรียบร้อย

--

--