应先构造 Uint8Array,再用 TextEncoder 处理文本字段,其余字段用类型数组直接写入;TextEncoder 仅负责 UTF-8 编码字符串,不可用于构造完整二进制协议包。

在 WebSocket 通信中,若需发送结构化二进制指令(如自定义协议的命令包),直接拼接字符串再用 TextEncoder 编码会出错——因为 TextEncoder 只处理 UTF-8 文本,不能安全表示任意字节(如 0x00、0xFF)。真正可靠的做法是:**先构造 Uint8Array,再通过 TextEncoder 处理其中的文本字段,其余字段用类型数组直接写入**。
明确 TextEncoder 的适用边界
TextEncoder 的唯一职责是将 JavaScript 字符串(UTF-16)按 UTF-8 编码为 Uint8Array。它不负责构造协议头、填充长度、打包二进制字段。常见误用是试图用它“编码整个指令包”,这会导致:
- 中文或特殊字符被多字节 UTF-8 编码,破坏固定偏移字段
- 无法插入
0x00等非字符字节 - 长度计算失准(UTF-8 变长编码 vs 协议要求的定长字段)
分段构造二进制指令:文本 + 二进制混合方案
假设协议格式为:[CMD:1B][LEN:2B][PAYLOAD:UTF8](1 字节命令,2 字节大端负载长度,后续为 UTF-8 编码的文本负载):
function buildCommand(cmd, payloadStr) {
const encoder = new TextEncoder();
const payloadBytes = encoder.encode(payloadStr); // ✅ 安全获取 UTF-8 字节
const len = payloadBytes.length;
// 分配总缓冲区:1(cmd) + 2(len) + payloadBytes.length
const buffer = new Uint8Array(1 + 2 + payloadBytes.length);
// 写入命令(1字节)
buffer[0] = cmd;
// 写入长度(2字节大端)
buffer[1] = (len >> 8) & 0xFF;
buffer[2] = len & 0xFF;
// 写入 UTF-8 负载(从索引3开始)
buffer.set(payloadBytes, 3);
return buffer;
}
// 使用
const packet = buildCommand(0x01, "你好");
socket.send(packet); // 直接发送 Uint8Array
处理含非文本字段的复杂协议
若协议含整数、浮点数、布尔等,必须用 DataView 或类型化数组视图操作:
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
立即学习“前端免费学习笔记(深入)”;
- 用
Uint8Array.buffer创建DataView,精确控制字节序和偏移 - 文本字段仍交由
TextEncoder.encode()生成字节数组,再.set()到目标位置 - 避免将数字转字符串再编码——那会变成 ASCII 字符,而非原始二进制值
例如写入一个 4 字节小端整数:view.setUint32(offset, value, true);写入字符串:uint8Array.set(encoder.encode(str), offset)。
接收端注意:WebSocket 的 binaryType 设置
确保 WebSocket 实例设置 socket.binaryType = 'arraybuffer'(默认是 'blob')。否则收到的二进制数据是 Blob,需额外读取:
- 发送前:无需额外处理,直接
send(Uint8Array)或send(ArrayBuffer) - 接收时:
socket.onmessage = e => { if (e.data instanceof ArrayBuffer) { ... } } - 解析时:用
new Uint8Array(e.data)得到可读视图,再用TextDecoder解码文本段


















