Mastering Real‑Time Chat in WeChat Mini‑Programs with WebSocket
This guide explains how to use WebSocket in a WeChat Mini‑Program to implement real‑time features such as live‑room comments, user join/leave events, likes, follows, and product shelf updates, covering protocol basics, handshake details, API usage, example code, heartbeat monitoring, and automatic reconnection strategies.
Preface
WebSocket is used to implement real‑time communication for live‑room comments, user entry/exit, likes, follows, and product shelf operations in a WeChat Mini‑Program.
What Is WebSocket?
WebSocket is a communication protocol that provides full‑duplex communication over a single TCP connection. It simplifies data exchange between client and server and allows the server to push data to the client after an initial handshake.
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 Explanations
Connection must be set to Upgrade to indicate the client wants to upgrade the connection.
Upgrade must be set to websocket to request the WebSocket protocol.
Sec-WebSocket-Key is a random string; the server concatenates it with the GUID 258EAFA5-E914-47DA-95CA-C5AB0DC85B11, computes a SHA‑1 hash, Base64‑encodes the result, and returns it as Sec-WebSocket-Accept to prevent ordinary HTTP requests from being mistaken for WebSocket upgrades.
Sec-WebSocket-Version indicates the supported version; RFC6455 requires version 13.
Origin is optional and identifies the page that initiated the connection, similar to Referer but containing only scheme and host.
WebSocket API in WeChat Mini‑Program
wx.connectSocket: creates a WebSocket connection. sotk.onOpen: listens for the connection‑open event. sotk.onClose: listens for the connection‑close event. sotk.onError: listens for error events. sotk.onMessage: listens for messages from the server (crucial for receiving data). sotk.send: sends data through the WebSocket (crucial for transmitting data).
Example usage:
var sotk = null;
var socketOpen = false;
var wsbasePath = "ws://开发者服务器 wss 接口地址/";
// Start WebSocket
webSocketStart(e) {
sotk = wx.connectSocket({
url: wsbasePath,
success: res => {
console.log('小程序连接成功:', res);
},
fail: err => {
console.log('出现错误啦!!' + err);
wx.showToast({ title: '网络异常!' });
}
});
this.webSokcketMethods();
},
// Listen to events
webSokcketMethods(e) {
let that = this;
sotk.onOpen(res => {
socketOpen = true;
console.log('监听 WebSocket 连接打开事件。', res);
});
sotk.onClose(onClose => {
console.log('监听 WebSocket 连接关闭事件。', onClose);
socketOpen = false;
});
sotk.onError(onError => {
console.log('监听 WebSocket 错误。错误信息', onError);
socketOpen = false;
});
sotk.onMessage(onMessage => {
var data = JSON.parse(onMessage.data);
console.log('监听WebSocket接受到服务器的消息事件。服务器返回的消息', data);
// ...handle different message types...
});
},
// Send a message
sendSocketMessage(msg) {
if (socketOpen) {
console.log('通过 WebSocket 连接发送数据', JSON.stringify(msg));
sotk.send({ data: JSON.stringify(msg) }, function (res) {
console.log('已发送', res);
});
}
},
// Close connection
closeWebsocket(str) {
if (socketOpen) {
sotk.close({
code: "1000",
reason: str,
success: function () {
console.log("成功关闭websocket连接");
}
});
}
}Implementation Logic
1. Message handling : onMessage receives data, parses the type field, and processes the payload accordingly.
2. Sending data : sendSocketMessage constructs a payload that includes a type field so the backend knows how to handle the message.
Key code snippet:
webSokcketMethods(e) {
this.websocket.onMessage(onMessage => {
console.log(this.data);
var data = JSON.parse(onMessage.data);
console.log('监听WebSocket接受到服务器的消息事件。服务器返回的消息', data);
if (data.client_id) {
this.setData({ client_id: data.client_id });
}
if (data.msg_type === 'init') {
this.joinLive();
}
// ...handle join, message, subscribe, leave, buy types...
});
},
joinLive() {
var data = {
msg_type: 'join',
room_id: this.data.liveRoomId,
live_id: this.data.liveId,
from_uid: this.data.anchorUid,
client_id: this.data.client_id,
is_anchor: true,
from_name: this.data.anchorName
};
console.log('通过 WebSocket 连接发送数据', JSON.stringify(data));
this.websocket.send({ data: JSON.stringify(data) });
},
goodsShelfOn(goodsId, goodsName, goodsPrice, defaultImage, status) {
var data = {
msg_type: 'on_off_shelf',
room_id: this.data.liveRoomId,
live_id: this.data.liveId,
from_uid: this.data.anchorUid,
client_id: this.data.client_id,
from_name: this.data.anchorName,
goods_id: goodsId,
goods_name: goodsName,
goods_price: goodsPrice,
default_image: defaultImage,
status: 'on'
};
console.log('通过 WebSocket 连接发送数据', JSON.stringify(data));
this.websocket.send({ data: JSON.stringify(data) });
}Heartbeat Detection and Automatic Reconnection
In production, the client must continuously monitor the connection state, send periodic heartbeats, and attempt reconnection with exponential back‑off when the socket closes or the network changes.
export default class websocket {
constructor({ heartCheck, isReconnection }) {
this._isLogin = false; // connection status
this._netWork = true; // network status
this._isClosed = false; // manual close flag
this._timeout = 3000; // heartbeat interval (ms)
this._timeoutObj = null;
this._connectNum = 0; // reconnection attempts
this._heartCheck = heartCheck; // enable heartbeat
this._isReconnection = isReconnection; // enable reconnection
this._onSocketOpened();
}
// Reset heartbeat timer
_reset() {
clearTimeout(this._timeoutObj);
return this;
}
// Start heartbeat
_start() {
let _this = this;
this._timeoutObj = setInterval(() => {
wx.sendSocketMessage({
data: JSON.stringify({ "msg_type": 'ping' }),
success(res) {
console.log(res);
console.log('发送心跳成功');
},
fail(err) {
console.log(err);
_this._reset();
}
});
}, this._timeout);
}
// Listen for socket close
onSocketClosed(options) {
wx.onSocketClose(err => {
console.log('当前websocket连接已关闭,错误信息为:' + JSON.stringify(err));
if (this._heartCheck) this._reset();
this._isLogin = false;
if (!this._isClosed && this._isReconnection) {
this._reConnect(options);
}
});
}
// Listen for network changes
onNetworkChange(options) {
wx.onNetworkStatusChange(res => {
console.log('当前网络状态:' + res.isConnected);
if (!this._netWork) {
this._isLogin = false;
if (this._isReconnection) this._reConnect(options);
}
});
}
// Socket opened – start heartbeat and send login payload
_onSocketOpened() {
wx.onSocketOpen(res => {
console.log('websocket已打开');
this._isLogin = true;
if (this._heartCheck) this._reset()._start();
wx.sendSocketMessage({ data: JSON.stringify({ "key": 'value' }) });
this._netWork = true;
});
}
// Receive messages
onReceivedMsg(callBack) {
wx.onSocketMessage(msg => {
if (typeof callBack === "function") {
callBack(msg);
} else {
console.log('参数的类型必须为函数');
}
});
}
// Initialize WebSocket connection
initWebSocket(options) {
if (this._isLogin) {
console.log('您已经登录了');
} else {
console.log('未登录');
wx.getNetworkType({
success(result) {
if (result.networkType != 'none') {
wx.connectSocket({
url: options.url,
success(res) {
if (typeof options.success === "function") options.success(res);
else console.log('参数的类型必须为函数');
},
fail(err) {
if (typeof options.fail === "function") options.fail(err);
else console.log('参数的类型必须为函数');
}
});
} else {
console.log('网络已断开');
this._netWork = false;
wx.showModal({
title: '网络错误',
content: '请重新打开网络',
showCancel: false,
success(res) { if (res.confirm) console.log('用户点击确定'); }
});
}
}
});
}
}
// Send a generic WebSocket message
sendWebSocketMsg(options) {
wx.sendSocketMessage({
data: options.data,
success(res) {
if (typeof options.success === "function") options.success(res);
else console.log('参数的类型必须为函数');
},
fail(err) {
if (typeof options.fail === "function") options.fail(err);
else console.log('参数的类型必须为函数');
}
});
}
// Reconnection with increasing intervals
_reConnect(options) {
let timer, _this = this;
if (this._connectNum < 20) {
timer = setTimeout(() => { this.initWebSocket(options); }, 3000);
} else if (this._connectNum < 50) {
timer = setTimeout(() => { this.initWebSocket(options); }, 10000);
} else {
timer = setTimeout(() => { this.initWebSocket(options); }, 450000);
}
this._connectNum += 1;
}
// Close the socket
closeWebSocket() {
wx.closeSocket();
this._isClosed = true;
}
}This class encapsulates connection management, heartbeat emission, automatic reconnection with exponential back‑off, and graceful shutdown, providing a robust foundation for real‑time features in WeChat Mini‑Programs.
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.
