Events and readyState
WebSocket เป็นออบเจกต์ที่ขับเคลื่อนด้วย event code ของคุณไม่ต้องคอย poll หรือบล็อกรอ แต่คุณผูก handler ไว้แล้วปล่อยให้การเชื่อมต่อเรียกกลับมาหาคุณเมื่อมีอะไรเกิดขึ้น มี event อยู่ สี่ ตัวพอดี และฟิลด์เดียว — readyState — ที่บอกเสมอว่าคุณอยู่ตรงไหน เชี่ยวชาญสิ่งเหล่านี้แล้ว API จะไม่มีอะไรเซอร์ไพรส์อีก
สี่ event
หัวข้อที่มีชื่อว่า “สี่ event”WebSocket บนเบราว์เซอร์ทุกตัวยิง event สี่ตัวเดียวกัน ไม่มากกว่านี้:
open— handshake สำเร็จ การเชื่อมต่อตอนนี้เป็นOPENและพร้อมใช้งานแล้ว นี่คือที่เดียวที่ปลอดภัยในการเริ่มส่งmessage— มีข้อความมาถึงจาก peer payload อยู่บนevent.dataclose— การเชื่อมต่อปิดลงแล้ว event นี้พกตัวเลขevent.codeและสตริงevent.reasonที่อธิบายว่าทำไมerror— มีบางอย่างผิดพลาด เป็นแค่ข้อมูลบอกกล่าวและจงใจให้คลุมเครือ (เพื่อความปลอดภัย) eventcloseมักจะตามมาเสมอ
คุณผูก handler ได้สองวิธี วิธีที่เร็วที่สุดคือผ่าน property on*:
const ws = new WebSocket('wss://example.com');ws.onopen = () => console.log('open');ws.onmessage = (event) => console.log('data:', event.data);ws.onerror = () => console.log('error');ws.onclose = (event) => console.log('closed', event.code, event.reason);หรือใช้ addEventListener ซึ่งช่วยให้คุณผูก handler ได้มากกว่าหนึ่งตัวต่อหนึ่ง event:
ws.addEventListener('message', (event) => console.log(event.data));readyState: ตัวเลขทั้งสี่
หัวข้อที่มีชื่อว่า “readyState: ตัวเลขทั้งสี่”ขณะที่ event บอกคุณว่าสิ่งต่าง ๆ เปลี่ยน เมื่อไหร่ readyState บอกคุณว่าสถานะปัจจุบันคืออะไร ในทุกขณะ เป็นตัวเลข และคลาสเปิดให้เข้าถึงค่าคงที่ที่มีชื่อสำหรับแต่ละค่า:
WebSocket.CONNECTING; // 0 — handshake in progressWebSocket.OPEN; // 1 — ready to send and receiveWebSocket.CLOSING; // 2 — close handshake underwayWebSocket.CLOSED; // 3 — finished, or never opened
if (ws.readyState === WebSocket.OPEN) { ws.send('safe to send now');}สองมุมมองนี้สอดคล้องกันอย่างลงตัว: event open ยิงตอนที่คุณเข้าสู่สถานะ 1 และ event close ยิงตอนที่คุณเข้าสู่สถานะ 3 การตรวจ ws.readyState === WebSocket.OPEN ก่อนส่งคือ guard มาตรฐานที่กันบั๊กแบบ “ฉันพยายามส่งเร็วเกินไปหรือช้าเกินไป”
event และสถานะประสานกันอย่างไร
หัวข้อที่มีชื่อว่า “event และสถานะประสานกันอย่างไร”นี่คือวงจรชีวิตเดียวกันจากบทแรก ตอนนี้กำกับด้วย event ที่ยิงในแต่ละการเปลี่ยนสถานะ:
stateDiagram-v2 [*] --> CONNECTING: new WebSocket() CONNECTING --> OPEN: open event CONNECTING --> CLOSED: error then close event OPEN --> CLOSING: close() / peer closes CLOSING --> CLOSED: close event OPEN --> CLOSED: drop, then close event note right of OPEN: message events may fire repeatedly here CLOSED --> [*]
event message พิเศษตรงที่: ไม่ใช่การเปลี่ยนสถานะ event นี้ยิงได้กี่ครั้งก็ได้ขณะที่คุณอยู่ในสถานะ OPEN ซึ่งนั่นแหละคือจุดประสงค์ทั้งหมดของการเชื่อมต่อแบบคงอยู่ยาวนาน
ดูการเปลี่ยนสถานะแบบสด
หัวข้อที่มีชื่อว่า “ดูการเปลี่ยนสถานะแบบสด”เดโมใช้ echo socket ในหน้าเว็บที่มี WebSocket API จริง จึงรันได้ทุกที่โดยไม่ต้องมี server เดโมล็อก readyState ในทุกขั้นตอนโดยใช้ค่าคงที่ที่มีชื่อ ในแอปจริงมีเพียงบรรทัดแรก — new WebSocket('wss://your-server') — เท่านั้นที่ต่างไป
ลองตามรอยผลลัพธ์เทียบกับไดอะแกรม: CONNECTING ตอนสร้าง, OPEN ใน handler ของ open, ยังคง OPEN เมื่อ message มาถึง, CLOSING ในวินาทีที่เรียก close() และ CLOSED เมื่อ event close ยิง — พกค่า code 1000 และ reason ที่เราส่งไปมาด้วย
| readyState | ค่า | ความหมาย |
|---|---|---|
| CONNECTING | 0 | กำลัง handshake |
| OPEN | 1 | เชื่อมต่อแล้ว พร้อมส่ง/รับ |
| CLOSING | 2 | กำลังปิด connection |
| CLOSED | 3 | ปิดแล้ว |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”ส่ง Message เมื่อ readyState ไม่ใช่ OPEN อาการ:
ws.send(data)ใน event handler โดยไม่ check state- CLOSING state ทำให้ throw error
- check ก่อนส่งเสมอ:
if (ws.readyState === WebSocket.OPEN) ws.send(data)
ไม่แยก onerror กับ onclose อาการ:
- handle แค่
onclose— ไม่รู้ว่า close เพราะ error หรือ normal onerrorเกิดก่อนoncloseเสมอเมื่อมี error- log ใน
onerrorเพื่อรู้สาเหตุ, reconnect ในonclose
💡 ตัวอย่างจากของจริง
GitHub Codespaces Terminal:
- ตรวจ readyState ก่อนส่ง input ทุก keystroke
- CONNECTING state → queue keystroke ไว้ส่งเมื่อ OPEN
Figma:
- แสดง “Reconnecting…” UI เมื่อ readyState เปลี่ยนจาก OPEN เป็น CLOSED
- user รู้ว่า connection ขาดและกำลัง reconnect