การดู : 231

22/04/2026 07:11น.

EP.42 การเพิ่มฟีเจอร์ Read Receipts (การแจ้งเตือนว่าอ่านแล้ว) ใน WebSocket Chat

EP.42 การเพิ่มฟีเจอร์ Read Receipts (การแจ้งเตือนว่าอ่านแล้ว) ใน WebSocket Chat

#Chat UX

#Chat Features

#Message Read Status

#WebSocket API

#Real-Time Chat

#Golang

#Go

#WebSocket

#Read Receipts

ทำไมต้องมี Read Receipts ใน WebSocket Chat?

Read Receipts หรือการแจ้งเตือนว่าอ่านแล้ว เป็นฟีเจอร์สำคัญที่ช่วยให้ผู้ใช้สามารถทราบได้ว่า:

  • ข้อความที่ส่งไปถึงปลายทางได้รับการอ่านแล้วหรือยัง
  • ช่วยให้ผู้ส่งมั่นใจว่าข้อความไม่ได้ถูกมองข้าม
  • สร้างประสบการณ์ที่ดีขึ้นในการสื่อสารแบบเรียลไทม์

ตัวอย่างแอปพลิเคชันที่ใช้ Read Receipts เช่น WhatsApp, Messenger, LINE ซึ่งจะแสดงเครื่องหมายถูกหรือไอคอนพิเศษเมื่อข้อความถูกอ่าน

โครงสร้างของระบบ Read Receipts ใน WebSocket Chat

  1. WebSocket Server - รับและส่งสถานะ "อ่านแล้ว" ให้กับผู้ใช้ในแชท
  2. Database - เก็บสถานะข้อความ (ยังไม่อ่าน/อ่านแล้ว)
  3. Frontend (Client-Side) - อัปเดต UI เมื่อข้อความถูกอ่าน

การเพิ่มฟีเจอร์ Read Receipts ใน WebSocket Server

1. อัปเกรด WebSocket Server ให้รองรับ Read Receipts

ไฟล์ websocket_server.go

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "sync"
    "github.com/gorilla/websocket"
)

type ReadReceipt struct {
    MessageID int    `json:"messageID"`
    Reader    string `json:"reader"`
}

type Message struct {
    ID      int    `json:"id"`
    Content string `json:"content"`
    Sender  string `json:"sender"`
    ReadBy  []string `json:"readBy"`
}

var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool { return true },
}

var (
    clients   = make(map[*websocket.Conn]bool)
    messages  = make(map[int]*Message)
    broadcast = make(chan ReadReceipt)
    mu        sync.Mutex
)

func handleConnections(w http.ResponseWriter, r *http.Request) {
    conn, _ := upgrader.Upgrade(w, r, nil)
    defer conn.Close()
    clients[conn] = true

    for {
        var receipt ReadReceipt
        err := conn.ReadJSON(&receipt)
        if err != nil {
            delete(clients, conn)
            break
        }
        broadcast <- receipt
    }
}

func handleMessages() {
    for {
        receipt := <-broadcast
        mu.Lock()
        if msg, exists := messages[receipt.MessageID]; exists {
            msg.ReadBy = append(msg.ReadBy, receipt.Reader)
        }
        mu.Unlock()
        
        for client := range clients {
            err := client.WriteJSON(receipt)
            if err != nil {
                client.Close()
                delete(clients, client)
            }
        }
    }
}

func main() {
    http.HandleFunc("/ws", handleConnections)
    go handleMessages()
    fmt.Println("WebSocket Server Running on Port 8080")
    http.ListenAndServe(":8080", nil)
}

2. การเพิ่ม Read Receipts ใน Frontend (Client-Side)

ไฟล์ client.js

const socket = new WebSocket("ws://localhost:8080/ws");
const messagesContainer = document.getElementById("messages");

socket.onmessage = (event) => {
    const data = JSON.parse(event.data);
    if (data.messageID) {
        document.getElementById(`msg-${data.messageID}`).innerText += " ✔ Read";
    }
};

function sendReadReceipt(messageID) {
    socket.send(JSON.stringify({ messageID, reader: "JohnDoe" }));
}

function displayMessage(id, content) {
    const msgElement = document.createElement("p");
    msgElement.id = `msg-${id}`;
    msgElement.innerText = content;
    msgElement.onclick = () => sendReadReceipt(id);
    messagesContainer.appendChild(msgElement);
}

การแสดง Read Receipts บน UI

ไฟล์ index.html

<div id="messages"></div>

3. การทดสอบระบบ

  1. รัน WebSocket Server
go run websocket_server.go
  1. เปิดหน้าเว็บหลายแท็บแล้วส่งข้อความ
  2. คลิกที่ข้อความเพื่อส่งสถานะ "อ่านแล้ว"

ท้าให้ลอง!

ลองเพิ่ม การแจ้งเตือนเฉพาะผู้ส่ง (Push Notification for Read Receipts) เพื่อแจ้งให้ผู้ส่งทราบทันทีเมื่อข้อความถูกอ่าน


EP ถัดไป

ใน EP.43, เราจะเพิ่ม ฟีเจอร์ปักหมุดข้อความ (Pinned Messages) ใน WebSocket Chat 🚀