How to Build Real‑Time Chat in WeChat Mini‑Programs Using WebSocket
This guide explains how to implement live‑room features such as comments, joining, leaving, likes, follows, and product updates in a WeChat mini‑program by using WebSocket for full‑duplex communication, covering the handshake process, API usage, message handling logic, and heartbeat‑based reconnection strategies.
Introduction
WebSocket provides full‑duplex, low‑latency communication over a single TCP connection. In WeChat Mini‑Programs it is commonly used for real‑time features such as live‑room comments, join/leave notifications, likes, follows, and product on/off‑shelf events.
What is WebSocket?
WebSocket is a protocol defined by RFC 6455. After an initial HTTP handshake the client and server keep a persistent connection, allowing either side to push data at any time without additional request/response cycles.
Communication Flow
Typical WebSocket Handshake
Client request
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13Server response
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chatField explanation
Connection: Upgradesignals a protocol upgrade request. Upgrade: websocket specifies the desired protocol. Sec-WebSocket-Key is a random Base64 string generated by the client. The server appends the GUID 258EAFA5-E914-47DA-95CA-C5AB0DC85B11, computes a SHA‑1 hash, Base64‑encodes the result, and returns it in Sec-WebSocket-Accept. Sec-WebSocket-Version: 13 is the only version required by the final RFC. Origin (optional) indicates the page that initiated the connection, similar to the HTTP Referer header but without path information.
WebSocket API in WeChat Mini‑Programs
wx.connectSocket– creates a WebSocket connection. socket.onOpen – fires when the connection is established. socket.onClose – fires when the connection is closed. socket.onError – fires on error events. socket.onMessage – receives messages from the server (core for data handling). socket.send – sends data to the server (core for transmitting data).
Basic usage example
var socket = null;
var socketOpen = false;
var wsBasePath = "ws://your-server-address/";
function startWebSocket() {
socket = wx.connectSocket({
url: wsBasePath,
success: res => console.log('Connection succeeded:', res),
fail: err => {
console.log('Connection error:', err);
wx.showToast({title: 'Network error'});
}
});
bindSocketEvents();
}
function bindSocketEvents() {
socket.onOpen(res => {
socketOpen = true;
console.log('WebSocket opened', res);
});
socket.onClose(err => {
console.log('WebSocket closed', err);
socketOpen = false;
});
socket.onError(err => {
console.log('WebSocket error', err);
socketOpen = false;
});
socket.onMessage(msg => {
var data = JSON.parse(msg.data);
console.log('Received message', data);
// Process different msg_type values here
});
}
function sendSocketMessage(msg) {
if (socketOpen) {
console.log('Sending message', JSON.stringify(msg));
socket.send({
data: JSON.stringify(msg),
success: res => console.log('Sent', res)
});
}
}
function closeWebSocket(reason) {
if (socketOpen) {
socket.close({
code: "1000",
reason: reason,
success: () => console.log('WebSocket closed')
});
}
}Message handling logic
The onMessage callback parses the incoming JSON, checks the msg_type field and updates UI or internal state accordingly. Outgoing messages must also contain a type (or msg_type) defined by the backend so the server can route the request.
Typical msg_type values include: init – initial data after login. join – user joins the live room. message – a chat comment. subscribe – a follow event. leave – user leaves the room. buy – product purchase or shelf change.
Heartbeat detection and automatic reconnection
In production a Mini‑Program must keep the connection alive, detect network changes, and reconnect when the socket is closed unexpectedly. The following class encapsulates these responsibilities.
export default class WebSocketManager {
constructor({ heartCheck = true, isReconnection = true } = {}) {
this._isLogin = false; // whether the socket is logged in
this._netWork = true; // current network status
this._isClosed = false; // whether the user manually closed the socket
this._timeout = 3000; // heartbeat interval (ms)
this._timeoutObj = null; // timer reference
this._connectNum = 0; // reconnection attempt counter
this._heartCheck = heartCheck; // enable/disable heartbeat
this._isReconnection = isReconnection; // enable/disable auto‑reconnect
this._onSocketOpened();
}
// ---------- heartbeat ----------
_reset() {
clearTimeout(this._timeoutObj);
return this;
}
_startHeartbeat() {
const that = this;
this._timeoutObj = setInterval(() => {
wx.sendSocketMessage({
data: JSON.stringify({ msg_type: 'ping' }),
success(res) { console.log('Heartbeat sent', res); },
fail(err) { console.log('Heartbeat failed', err); that._reset(); }
});
}, this._timeout);
}
// ---------- socket event bindings ----------
_onSocketOpened() {
wx.onSocketOpen(res => {
console.log('WebSocket opened');
this._isLogin = true;
if (this._heartCheck) this._reset()._startHeartbeat();
// send an optional login payload after the connection is ready
wx.sendSocketMessage({ data: JSON.stringify({ key: 'value' }) });
this._netWork = true;
});
}
onSocketClosed(options) {
wx.onSocketClose(err => {
console.log('WebSocket closed:', JSON.stringify(err));
if (this._heartCheck) this._reset();
this._isLogin = false;
if (!this._isClosed && this._isReconnection) this._reConnect(options);
});
}
onNetworkChange(options) {
wx.onNetworkStatusChange(res => {
console.log('Network status:', res.isConnected);
if (!this._netWork && this._isReconnection) this._reConnect(options);
});
}
onReceivedMsg(callback) {
wx.onSocketMessage(msg => {
if (typeof callback === 'function') {
callback(msg);
} else {
console.log('Callback must be a function');
}
});
}
// ---------- connection management ----------
initWebSocket(options) {
if (this._isLogin) {
console.log('Already logged in');
return;
}
wx.getNetworkType({
success: result => {
if (result.networkType !== 'none') {
wx.connectSocket({
url: options.url,
success: res => typeof options.success === 'function' && options.success(res),
fail: err => typeof options.fail === 'function' && options.fail(err)
});
} else {
console.log('Network disconnected');
this._netWork = false;
wx.showModal({ title: 'Network error', content: 'Please reconnect', showCancel: false });
}
}
});
}
sendWebSocketMsg(options) {
wx.sendSocketMessage({
data: options.data,
success: res => typeof options.success === 'function' && options.success(res),
fail: err => typeof options.fail === 'function' && options.fail(err)
});
}
// ---------- reconnection strategy (exponential back‑off) ----------
_reConnect(options) {
let delay;
if (this._connectNum < 20) {
delay = 3000; // first 20 attempts: 3 s interval
} else if (this._connectNum < 50) {
delay = 10000; // next 30 attempts: 10 s interval
} else {
delay = 450000; // thereafter: 7.5 min interval
}
setTimeout(() => this.initWebSocket(options), delay);
this._connectNum += 1;
}
closeWebSocket() {
wx.closeSocket();
this._isClosed = true;
}
}This class provides:
Automatic heartbeat transmission to keep the TCP connection alive.
Detection of socket closure and network status changes.
Exponential back‑off reconnection logic to avoid hammering the server.
Simple wrappers for sending and receiving messages.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Open Source Tech Hub
Sharing cutting-edge internet technologies and practical AI resources.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
