Receiving Messages

1. Handling Message Events

Event FieldType
event.datastring | Blob | ArrayBuffer
event.originstring
event.targetWebSocket

Example: Router by type

const handlers = { "chat.message": onChat, "presence": onPresence };
ws.addEventListener("message", (e) => {
  const msg = JSON.parse(e.data);
  handlers[msg.type]?.(msg.payload);
});

2. Parsing Text Messages

FormatParse
JSONJSON.parse(e.data)
CSV/TSVCustom split
PlainDirect string

3. Parsing JSON Messages

Example: Safe parse

function safeParse(raw) {
  try { return JSON.parse(raw); }
  catch { return null; }
}
ConcernMitigation
Malformed JSONWrap in try/catch
Prototype pollutionAvoid __proto__ keys
Large payloadsStream / chunk

4. Validating Message Format

Example: Zod schema

import { z } from "zod";
const ChatMsg = z.object({ "type": z.literal("chat.message"), "text": z.string().max(2000) });
const result = ChatMsg.safeParse(parsed);
if (!result.success) return reject(result.error);
LibraryLang
zodTS
valibotTS
ajv (JSON Schema)JS

5. Handling Message Order

GuaranteeWebSocket
In-order (single connection)Yes (TCP)
Across reconnectsNo — use sequence IDs
Across multiple socketsNo — single source-of-truth or seq

6. Handling Binary Messages

Example: Branch on type

ws.binaryType = "arraybuffer";
ws.addEventListener("message", (e) => {
  if (typeof e.data === "string") handleText(e.data);
  else if (e.data instanceof ArrayBuffer) handleBinary(new DataView(e.data));
});
binaryTypeIncoming Type
"blob"Blob
"arraybuffer"ArrayBuffer

7. Reading Blob Data

Example: Blob → ArrayBuffer

ws.addEventListener("message", async (e) => {
  if (e.data instanceof Blob) {
    const buf = await e.data.arrayBuffer();
    processBinary(buf);
  }
});
MethodReturns
blob.arrayBuffer()Promise<ArrayBuffer>
blob.text()Promise<string>
blob.stream()ReadableStream

8. Processing Typed Arrays

Example: Decode header + payload

function decode(view) {
  const type = view.getUint8(0);
  const len  = view.getUint32(1, false); // big-endian
  const body = new Uint8Array(view.buffer, 5, len);
  return { type, body };
}
StepAPI
Wrap buffernew DataView(buf)
Read fieldsgetUint8/16/32/Float32
Slicenew Uint8Array(buf, offset, len)

9. Implementing Message Queue

Example: Async iterator queue

function makeQueue(ws) {
  const buf = [], waiters = [];
  ws.addEventListener("message", (e) => {
    if (waiters.length) waiters.shift()(e.data);
    else buf.push(e.data);
  });
  return {
    async next() {
      if (buf.length) return buf.shift();
      return new Promise(res => waiters.push(res));
    }
  };
}
PatternUse
Async iteratorfor-await loops
EventTarget bridgeLibrary boundaries
ObservableRxJS integration

10. Handling Large Messages

TechniqueDetail
App-level chunkingSplit into ordered frames with seq
Streaming reassemblyMaintain buffer per message ID
Out-of-band transferUse HTTP for large blobs, WS for notify
Warning: Default ws server maxPayload is 100 MiB. Tune both client and server limits to prevent close 1009.