Sending Messages
1. Sending Text Messages
| Method | Accepts |
ws.send(string) | UTF-8 text frame (opcode 0x1) |
ws.send(ArrayBuffer) | Binary frame (0x2) |
ws.send(TypedArray) | Binary frame |
ws.send(Blob) | Binary frame |
Warning: Calling send() when readyState !== OPEN throws InvalidStateError.
2. Sending JSON Data
Example: Typed message envelope
function emit(type, payload) {
ws.send(JSON.stringify({ "type": type, "id": crypto.randomUUID(), "ts": Date.now(), "payload": payload }));
}
emit("chat.message", { "room": "general", "text": "hi" });
| Field | Purpose |
type | Dispatch key |
id | Correlation / dedup |
ts | Client timestamp |
payload | Type-specific data |
3. Checking Buffer Amount
Example: Backpressure-aware send
const MAX_BUFFER = 1 * 1024 * 1024; // 1 MB
function safeSend(data) {
if (ws.bufferedAmount > MAX_BUFFER) return false;
ws.send(data);
return true;
}
| Property | Detail |
bufferedAmount | Bytes queued in user agent, not yet on wire |
| Updated | After each send() |
| Reaches 0 | When fully flushed to network |
4. Queuing Messages
Example: Pre-open queue
const queue = [];
function send(msg) {
if (ws.readyState === WebSocket.OPEN) ws.send(msg);
else queue.push(msg);
}
ws.addEventListener("open", () => { while (queue.length) ws.send(queue.shift()); });
| Strategy | When |
| FIFO queue | Order matters |
| Coalesce | Latest-state wins (e.g. cursor) |
| Drop oldest | Bounded memory |
5. Validating Message Size
| Limit | Typical |
| Browser per-frame | Unlimited (memory-bound) |
| ws library default (Node) | 100 MB (maxPayload) |
Nginx client_max_body_size | N/A (different mechanism) |
| Recommended | ≤ 64 KB / msg |
6. Handling Send Errors
Example: Guarded send
try { ws.send(data); }
catch (err) {
if (err.name === "InvalidStateError") queue.push(data);
else throw err;
}
| Error | Meaning |
InvalidStateError | Socket not OPEN |
SyntaxError | Invalid UTF-8 in string |
7. Sending Binary Data
Example: Send ArrayBuffer
const buf = new ArrayBuffer(4);
new DataView(buf).setUint32(0, 0xDEADBEEF);
ws.send(buf);
| Type | Frame |
ArrayBuffer | Binary (0x2) |
Blob | Binary |
Uint8Array etc. | Binary |
8. Sending Typed Arrays
| Typed Array | Bytes / Element |
Uint8Array | 1 |
Int16Array | 2 |
Float32Array | 4 |
BigInt64Array | 8 |
Note: Endianness is little-endian on most platforms; encode explicitly with DataView for cross-platform protocols.
9. Implementing Message Batching
Example: Time-window batcher
let pending = [], timer = null;
function batchSend(msg) {
pending.push(msg);
timer ??= setTimeout(() => {
ws.send(JSON.stringify({ "type": "batch", "items": pending }));
pending = []; timer = null;
}, 20);
}
| Trigger | Use |
| Time window | Even update rate |
| Count threshold | Bounded latency |
| Size threshold | Bandwidth efficient |
10. Compressing Messages
| Approach | Trade-off |
| permessage-deflate (auto) | Negotiated extension; CPU cost |
| App-level gzip/brotli | Manual; better control |
| Binary format (MessagePack/Protobuf) | Smaller than JSON+deflate often |